Django 4 Model Forms - Adding Widgets Code Syntax - django-forms

I am new to Django and ModelForms and I am having issues adding widgets. My problems are that: A - I am struggling to find much information on the subject of ModelForms and B - The information I have found all seems to differ. Below is a snippet of my current code. This is giving me an error "forms is not defined". I have also tried the options below in various combinations, all of which throw up errors:
"from django import forms"
class EggCollectionForm(forms.ModelForm)
Removing "forms." from before "IntegerField"
Any assistance and guidance would be greatly appreciated. Thank you.
from django.forms import ModelForm, widgets
from .models import EggCollection, FeedingTime, CoopCleaning
class EggCollectionForm(ModelForm):
class Meta:
model = EggCollection
fields = ('date',
'qty_egg_trays')
widgets = {
'qty_egg_trays': forms.IntegerField(attrs={'class':
'egg-collection-qty-input \
saleable-eggs-input \
average-weight-input',
'id': 'qty-egg-trays',
'name': 'qty_egg_trays',
'placeholder': 'Qty Laid Trays',
'value': ''})}

IntegerField is for Models, NumberInput is for forms... at least I think. Just taking a crack at it.
class EggCollectionForm(ModelForm):
class Meta:
model = EggCollection
fields = ('date',
'qty_egg_trays')
widgets = {
'qty_egg_trays': forms.NumberInput(attrs={'class':
'egg-collection-qty-input \
saleable-eggs-input \
average-weight-input',
'id': 'qty-egg-trays',
'name': 'qty_egg_trays',
'placeholder': 'Qty Laid Trays',
'value': ''})}

Related

How to get the current logged-in user for schema? (django graphql api)

my goal: I am trying to return all the fields of the posts if the user has an id of 1, and I want to return only 3 fields if else.
My problem is: in the query or mutations I can do info.context.user.id but in the schema I can't do that.
Here in my following code you can noticed his undefined variable current_loggedin_user which I don't know how to get its value.
import graphene
from graphene_django import DjangoObjectType
from . import models
from django.conf import settings
class Posts(DjangoObjectType):
class Meta:
model = models.ExtendUser
if (current_logedin_user.id==1):
field = '__all_'
else:
fields = ['username', 'id', 'imageUrl']
You need to include all fields that are visible to anyone to the schema, and then customize the resolver methods for the fields that you want to hide for some users. For example:
class Posts(DjangoObjectType):
class Meta:
model = models.ExtendUser
def resolve_restricted_field(self, info):
if info.context.user.id == 1:
return self.restricted_field
return None
For more examples, see How to limit field access on a model based on user type on Graphene/Django?
Try something like this
class Posts(DjangoObjectType):
class Meta:
model = models.ExtendUser
class Query(ObjectType):
fields = graphene.List(Posts)
def resolve_fields(self, info, **kwargs):
if info.context.user.pk == 1:
return ExtendUser.objects.all()
return ExtendUser.objects.values_list('username', 'id', 'imageUrl', flat=True)

How can I display ordering using drf_yasg

How to deal with ordering in drf_yasg?
I have a View:
class ContentView(ModelViewSet):
....
ordering_fields = ['price',]
But when I open swagger I cant see this possibility.
I found a solution, maybe somebody need this too.
I use django_filters package and in this case we should use filter_class on our view and there we can define ordering as we need.
Example:
from django_filters import rest_framework as filters, OrderingFilter
from contents.models import Content
class ContentFilter(filters.FilterSet):
order = OrderingFilter(
# tuple-mapping retains order
fields=(
('price', 'price'),
),
field_labels={
'price': 'Content price',
}
)
class Meta:
model = Content
fields = ['price']
# my view in views.py
class ContentView(ModelViewSet):
filter_class = ContentFilter
.....
Now you can use ordering ?order=price or ?order=-price and you can see it on swagger docs
More info about OrderingFilter in django_filters here
from rest_framework.filters import OrderingFilter
class OrderingFilterWithSchema(OrderingFilter):
def get_schema_fields(self, view):
self.ordering_description = [enter image description here][1]ordering choicese: " + ', '.join(view.ordering_fields)
return super().get_schema_fields(view)
And in your view:
class ListView(ListAPIView):
filter_backends = [OrderingFilterWithSchema]
ordering_fields = ['price', 'created_at', 'manufacturer_year', 'spent_kilometers']
And the URL will be like:
?ordering=-price or ordering=price
...etc

Attach author to POST request to create an object

It's probably very basic, but I am starting to learn Django REST Framework. So far I've succeeded with read-only operations. And now I got stuck on this problem.
I have a model:
class PersonComment(AbstractComment):
person = models.ForeignKey(Person, on_delete=models.PROTECT)
author = models.ForeignKey('auth.User')
body = models.TextField(default='', blank=False)
(Here author is the author of the comment and person is a person this comment relates to; it's a genealogical site.) And a related serialiser:
class PersonCommentSerialiser(serializers.HyperlinkedModelSerializer):
class Meta:
model = PersonComment
fields = ('url', 'body', 'person', 'author')
In my HTML page, I expect a user to submit a comment by providing "body", the rest should be auto-filled. What is the best practice for filling in the "author"? In my pre-DRF Django exercises, I was doing something like this in the view:
comment = PersonComment.objects.create(
author=request.user,
body=new_comment_body,
person=person
)
But if I understand everything I've read so far, this is not the way in DRF. Any help is much appreciated.
I would do this using the default attribute in serializer fields.
class PersonCommentSerialiser(serializers.HyperlinkedModelSerializer):
author = serializers.PrimaryKeyRelatedField(read_only=True, default=CurrentUserDefault())
class Meta:
model = PersonComment
fields = ('url', 'body', 'person', 'author')
CurrentUserDefault is a class predefined in Django REST framework for exactly this purpose. This way you don't have to overwrite create in your own serializer.
I was not sure what is the difference between person and author. But you should be able to do something similar I suppose.

Foreign key field disappears in swagger docs after adding depth attribute in Serializer

Whenever I define the depth attribute, the foreign key field from swagger docs in POST section disappears. That seems strange because I required depth = 1 when I want related data in my GET request. So I can not remove this in order to get this related field parameter in the POST section.
Here is the case.
Model:
from django.db import models
from django.conf import settings
# Create your models here.
User = settings.AUTH_USER_MODEL
class Todo(models.Model):
user = models.ForeignKey(User)
title = models.CharField("Title", max_length=255)
completed = models.BooleanField("Completed")
Serializer without depth =1.
from rest_framework import serializers
from models import Todo
class TodoSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Todo
Swagger output:
Now If I add depth = 1 than Swagger does not display related field.
Let me know if anyone has any clue about this.
Thanks :)
Finally after digging into this, I come up with solution by which we can avoid this issue and achieve the expected solution.
So the solution is "Instead of using depth = 1 attribute we can using related serializer instance it self where it works similar to depth functionality."
Here is tested solution
Model:
from django.db import models
from django.conf import settings
User = settings.AUTH_USER_MODEL
class Todo(models.Model):
user = models.ForeignKey(User)
title = models.CharField("Title", max_length=255)
completed = models.BooleanField("Completed")
Serializer
from rest_framework import serializers
from django.conf import settings
from models import Todo
User = settings.AUTH_USER_MODEL
class UserSerializer(serializers.HyperlinkedSerializer):
class Meta:
model = User
class TodoSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer()
class Meta:
model = Todo
fields = ('user', 'title', 'completed')
Swagger Output:
This solution is kind of different approach in order to achieve the required functionality, But still I am expecting an official solution from django-rest-swagger team, Even I have posted the same query on django-rest-swagger github repo here.
One solution is to just don't use depth and override to_representation method of serializer:
class TodoSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
def to_representation(self, instance):
r = super(TodoSerializer, self).to_representation(instance)
r.update({'user': UserSerializer().to_representation(instance.user)})
return r
This way, in post everything will be as it was, and in get when return json of todo then to_representation will be called and will add user to json data.
You need to update your serialzer as follows
class TodoSerializer(serializers.HyperlinkedModelSerializer):
creator = serializers.RelatedField(queryset=User.objects.all())
class Meta:
model = Todo
fields = ("name", "task", "creator")
depth = 1
you need to mentions fields and RelatedField in your serializers

django rest framework choosing between two possible views for hyperlinked field

So I have two different API views on to User, one that superusers can use, and one that normal users can use.
At the moment, the problem is that my hyperlinks are going to auth_users view by default, instead of to the users view.
i.e.
'url': 'localhost:8000/auth_users/5/'
instead of
'url': 'localhost:8000/users/5/'
Here are extracts from the relevant files...
* URLS *
router =
routers.SimpleRouter()
router.register(r'auth_users', UserAPI.AdminUserViewSet)
urlpatterns = patterns('',
url(r'^', include(router.urls)),
url(r'^users/?$', UserAPI.CreateOrList.as_view(), name='users'),
url(r'^users/(?P<pk>[0-9]+)/?$', UserAPI.RetrieveUpdateOrDestroy.as_view()),
...
)
* serializer *
class basic_user_serializer(serializers.HyperlinkedModelSerializer):
url = HyperlinkedIdentityField(view_name='users')
class Meta:
model = User
fields = ['url', 'email', 'username']
* views *
class CreateOrList(generics.GenericAPIView):
"""
List all users, or create a new one.
"""
serializer_class = create_user_serializer
class RetrieveUpdateOrDestroy(generics.RetrieveUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = create_user_serializer
I've had a look at the docs (linked below) but am not sure if this is explained...
http://django-rest-framework.org/api-guide/relations.html#hyperlinkedidentityfield
Anyone know how to fix it?
Cheers.
Oh, I fixed it.
I got rid of the auth_user view to see what would happen, and it threw an error page saying it couldn't find 'user-detail'.
I then changed the name of the users view to 'user-detail', re-enabled the auth_user view, and it works properly now.
No idea why, though - didn't I tell it to use 'users' instead of 'user-detail'??

Resources