Django Rest Framework - Add fields to JSON - json

Now I return a JSON file with the model fields and their values. I want to add some extra fields to the JSON that are not present in the model (I want to add a new field that specifies if an user can modify or not the diagnostic based on the permissions of the view). How I can do this?
models.py
class Diagnostic(models.Model):
Center = models.TextField(blank=True)
Author = models.TextField(blank=True)
Email = models.EmailField(blank=True)
Date = models.DateField(null = True, blank=True)
views.py
class DiagnosticViewSet(viewset.ModelViewSet):
model = Diagnostic
permission_classes = [GroupPermission]
serializers.py
class DiagnosticSerializer(serializers.ModelSerializer):
class Meta:
model = Diagnostic

Add this to your views
def list(self, request, *args, **kwargs):
response = super(Classname, self).list(request, *args, **kwargs)
try:
response.data['permission'] = 'give your permission'
except:
pass
return response

You add them to the serializer.
class DiagnosticSerializer(serializers.ModelSerializer):
auth_status = serializers.SerializerMethodField('get_auth_status')
class Meta:
model = Diagnostic
def get_auth_status(self, obj):
if obj.has_auth():
return True
return False

You have to use following code for the url localhost/diagnostics/1
from rest_framework.response import Response
def retrieve(self, request, *args, **kwargs):
self.object = self.get_object()
serializer = self.get_serializer(self.object)
data = serializer.data
data['permission'] = 'give your permission'
return Response(data)

Related

Django complete form as signed up user

After you sign up, you are prompted to a page that contains a form used for gathering additional information about the new user and after that it redirects you to the login page. The problem is that the form doesn't submit if i don't specify the {{form.user}} instance in the html file. Probably because the user_id is not recognized by default. When i specify it, the form let me chooses from already existing users, and i would like it to go with the logged in user by default.
views.py
class CreateInfoView(CreateView):
model = AdditionalInfoModel
form_class = AdditionallnfoModelForm
template_name = "user_ski_experience/additional_info.html"
def get_form_kwargs(self):
variable_to_send = super(CreateInfoView, self).get_form_kwargs()
variable_to_send.update({'pk': None})
variable_to_send.update({'pk_user': self.request.user.pk})
return variable_to_send
def form_valid(self, form):
form.instance.created_by = self.request.user
return super().form_valid(form)
def get_success_url(self):
return reverse('login')
forms.py
class AdditionallnfoModelForm(forms.ModelForm):
class Meta:
model = AdditionalInfoModel
fields = '__all__'
def __init__(self, pk, *args, **kwargs):
pk_user = kwargs.pop('pk_user')
super(AdditionallnfoModelForm, self).__init__(*args, **kwargs)
self.pk = pk
self.fields['user'].disabled = True
self.fields['user'].initial = pk_user
for el in self.fields:
self.fields[el].label = False
def clean(self):
return self.cleaned_data
How can i solve this ?
class AdditionalInfoModel(models.Model):
objects = None
skill_choices = (('Beginner', 'BEGINNER'),
('Intermediate', 'INTERMEDIATE'),
('Expert', 'EXPERT'))
user = models.OneToOneField(User, on_delete=models.CASCADE)
country = models.CharField(max_length=30, blank=True)
city = models.CharField(max_length=30, blank=True)
assumed_technical_ski_level = models.CharField(max_length=30,
choices=skill_choices)
years_of_experience = models.PositiveIntegerField(blank=True)
money_to_spend = models.PositiveIntegerField(blank=True)
resort_choice = models.ForeignKey(Resorts, on_delete=models.CASCADE,
blank = True, null = True)
def __str__(self):
return self.user.username

`category` and `tag` shared by multiple wagtail page types

I have a Django+Wagtail website, and have category and tag created to be applied to blog posts.
from taggit.models import Tag as TaggitTag
from taggit.models import TaggedItemBase
class PostList(RoutablePageMixin, Page):
template = "Post_List.html"
intro = RichTextField(blank=True)
content_panels = Page.content_panels + [
FieldPanel("intro")
]
subpage_types = [
"PostDetail",
]
parent_page_type = [
"HomePage",
]
# Each 'search / category / tag / author' will generate a separate 'PostList' page with its own 'context',
# hence for 'Pagination' for all 'PostList' pages, we only need to implement in 'get_context()'
def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
# For Pagination
page_id = request.GET.get("page")
paginator = Paginator(self.posts, 3) # 'posts' is defined in 'def post_list()' and 'def get_posts()' as below.
try:
paginator_page = paginator.page(page_id)
except PageNotAnInteger:
paginator_page = paginator.page(1)
page_id = 1
except EmptyPage:
paginator_page = paginator.page(1)
page_id =1
context['paginator_page'] = paginator_page
context['total_num_pages'] = paginator.num_pages
# By default, Paginator.get_elided_page_range(number, *, on_each_side=3, on_ends=2)
context['elided_page_range'] = paginator.get_elided_page_range(page_id, on_each_side=5, on_ends=2)
return context
def get_posts(self):
return PostDetail.objects.descendant_of(self).live()
#route(r'^tag/(?P<tag>[-\w]+)/$')
def post_by_tag(self, request, tag, *args, **kwargs):
self.search_type = 'tag'
self.search_term = tag
self.posts = self.get_posts().filter(tags__name=tag)
return Page.serve(self, request, *args, **kwargs)
#route(r'^category/(?P<category>[-\w]+)/$')
def post_by_category(self, request, category, *args, **kwargs):
self.search_type = 'category'
self.search_term = category
self.posts = self.get_posts().filter(categories__category__name=category)
return Page.serve(self, request, *args, **kwargs)
#route(r'^user/(?P<user>[-\w]+)/$')
def post_by_user(self, request, user, *args, **kwargs):
self.search_type = 'user'
self.search_term = user
self.posts = self.get_posts().filter(owner__username=user)
return Page.serve(self, request, *args, **kwargs)
#route(r'^$')
def post_list(self, request, *args, **kwargs):
self.posts = self.get_posts()
return Page.serve(self, request, *args, **kwargs)
#route(r'^search/$')
def post_search(self, request, *args, **kwargs):
search_query = request.GET.get('q', None)
self.posts = self.get_posts()
if search_query:
self.posts = self.posts.filter(body__contains=search_query)
self.search_term = search_query
self.search_type = 'search'
return Page.serve(self, request, *args, **kwargs)
class PostDetail(Page):
template = "Post_Detail.html"
body = MarkdownField()
tags = ClusterTaggableManager(through="PostDetailTag", blank=True)
#register_snippet
class Category(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=100)
panels = [
FieldPanel("name"),
FieldPanel("slug"),
]
def __str__(self):
return self.name
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"
ordering = ["name"]
#register_snippet
class Tag(TaggitTag):
class Meta:
proxy = True
# Intermediate Models for ManyToMany Relationship
class PostDetailCategory(models.Model):
post = ParentalKey("PostDetail", on_delete=models.CASCADE, related_name="categories")
category = models.ForeignKey("Category", on_delete=models.CASCADE, related_name="post_details")
panels = [
SnippetChooserPanel("category"),
]
class Meta:
unique_together = ("post", "category")
class PostDetailTag(TaggedItemBase):
content_object = ParentalKey("PostDetail", on_delete=models.CASCADE)
Now, I am about to creating another wagtail page type "SurveyPoll", and want to have tag and category applied as well.
What is the best practice for this deployment, same tag and category applied to different wagtail page types via ManyToMany relationship ?
Which type of ManyToMany relationship deployment is better, tag or category ? Personally, I prefer the category way as it allows me to choose from a list of existing category in wagtail admin edit page.

How do I make my model's depdent fields appear in my JSON using Django serializers?

I'm using Django 2.0 and Python 3.7. I have the following models ...
from django.db import models
from address.models import AddressField
from phonenumber_field.modelfields import PhoneNumberField
from address.models import State
from address.models import Country
class CoopTypeManager(models.Manager):
def get_by_natural_key(self, name):
return self.get_or_create(name=name)[0]
class CoopType(models.Model):
name = models.CharField(max_length=200, null=False)
objects = CoopTypeManager()
class Meta:
unique_together = ("name",)
class Coop(models.Model):
name = models.CharField(max_length=250, null=False)
type = models.ForeignKey(CoopType, on_delete=None)
address = AddressField(on_delete=models.CASCADE)
enabled = models.BooleanField(default=True, null=False)
phone = PhoneNumberField(null=True)
email = models.EmailField(null=True)
web_site = models.TextField()
And then I created the following serializers ...
from rest_framework import serializers
from maps.models import Coop, CoopType
class CoopSerializer(serializers.ModelSerializer):
class Meta:
model = Coop
fields = ['id', 'name', 'type', 'address', 'enabled', 'phone', 'email', 'web_site']
def create(self, validated_data):
"""
Create and return a new `Snippet` instance, given the validated data.
"""
return Coop.objects.create(**validated_data)
def update(self, instance, validated_data):
"""
Update and return an existing `Coop` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
instance.type = validated_data.get('type', instance.type)
instance.address = validated_data.get('address', instance.address)
instance.enabled = validated_data.get('enabled', instance.enabled)
instance.phone = validated_data.get('phone', instance.phone)
instance.email = validated_data.get('email', instance.email)
instance.web_site = validated_data.get('web_site', instance.web_site)
instance.save()
return instance
class CoopTypeSerializer(serializers.ModelSerializer):
class Meta:
model = CoopType
fields = ['id', 'name']
def create(self, validated_data):
"""
Create and return a new `CoopType` instance, given the validated data.
"""
return CoopType.objects.create(**validated_data)
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
I'm trying to create an API to display my models as JSON. I created this views file
from maps.models import Coop
from maps.serializers import CoopSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class CoopList(APIView):
"""
List all coops, or create a new coop.
"""
def get(self, request, format=None):
coops = Coop.objects.all()
serializer = CoopSerializer(coops, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = CoopSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class CoopDetail(APIView):
"""
Retrieve, update or delete a coop instance.
"""
def get_object(self, pk):
try:
return Coop.objects.get(pk=pk)
except Coop.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
coop = self.get_object(pk)
serializer = CoopSerializer(coop)
return Response(serializer.data)
def put(self, request, pk, format=None):
coop = self.get_object(pk)
serializer = CoopSerializer(coop, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
coop = self.get_object(pk)
coop.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
However, my dependent model, CoopType, is not getting displayed as JSON. Only its primary key is getting displayed, e.g. ...
{
"id": 915,
"name": "Young Men's Educational Network",
"type": 10,
"address": 790,
"enabled": true,
"phone": null,
"email": null,
"web_site": "www.ymenchi.com/"
},
How do I get my dependent model to appear in my JSON?
Override the to_representation(...) method of the Serializer
class CoopSerializer(serializers.ModelSerializer):
# other code snippets
def to_representation(self, instance):
rep = super().to_representation(instance)
rep['type'] = CoopTypeSerializer(instance.type).data
return rep
Reference: DRF: Simple foreign key assignment with nested serializers?

Django serializer is not returning JSON data

I have a model Domain:
class Domain(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
And a corresponding serializer:
class DomainSerializer(serializers.ModelSerializer):
class Meta:
model = Domain
fields = ('name',)
I'm trying to serialize a queryset in a view like this:
def getDomains(request):
domains = Domain.objects.filter(name__startswith=request.GET['name_startsWith'])
data = DomainSerializer(domains, many=True)
print(data.data)
return HttpResponse(data.data)
This is not working correctly, and data.data is :
[OrderedDict([('name', 'Math')])]
I would like to have a JSON object, something like:
{'name': 'Math'}.
Try using JsonResponse to return the data:
from django.http import JsonResponse
.....
return JsonResponse(data.data)

Column 'user_id' cannot be null django

I seek to create a post with a form where a registered user creates and inserts the primary key id in the db but this does not give me the following error Column 'user_id' can not be null
This is my models.py
class posts(models.Model):
titulo = models.CharField(max_length=180, unique=True)
slug = models.SlugField(max_length=180, editable=False)
contenido = models.TextField()
categoria = models.ForeignKey(categorias)
user = models.ForeignKey(User)
tags = models.CharField(max_length=200)
creado = models.DateTimeField(auto_now_add=True)
modificado = models.DateTimeField(auto_now=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.titulo)
super(posts, self).save(*args, **kwargs)
def __str__(self):
return self.titulo
This is my view.py
def addPosts(request):
if request.method == "POST":
form = addPostForm(request.POST)
if form.is_valid():
add = form.save(commit=False)
#add.user = User.objects.get(id=request.user)
add.save()
form.save_m2m()
return HttpResponseRedirect('/')
else:
form = addPostForm ()
ctx = {'form': form}
return render_to_response('posts/add.html', ctx, context_instance=RequestContext(request))
This is forms.py
class addPostForm(forms.ModelForm):
class Meta:
model = posts
exclude = {'slug','user', 'creado'}
some solution to this problem?
Request.user returns the current user object. No need to do a lookup.
add.user = request.user
in your view
If tying to the Django built-in user, you're going to want to do it differently from your model:
user = models.ForeignKey(User)
Consider defining this in your settings and instead, use:
user = models.ForeignKey(settings.AUTH_USER_MODEL)
See the documentation here: https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#referencing-the-user-model
This will also future-proof you if you decide to extend the Django base user model in the future.