How to auto specify form value in django form - django-forms

I am working with Django forms
this is my model
class Genre(models.Model):
gen_name = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.gen_name
this is my form
class Genreform(forms.ModelForm):
class Meta:
model=Genre
fields={ 'gen_name','pub_date'}
but i want to manually assign the pub_date (i.e. user dont have to fill that)
so i did
class Genreform(forms.ModelForm):
pub_date=forms.DateTimeField(widget=forms.HiddenInput(),initial=timezone.now())
class Meta:
model=Genre
fields={ 'gen_name'}
but this is not working
this is my request handler
def create_genre(request):
#pdb.set_trace()
if request.POST:
form = Genreform(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('http://127.0.0.1:8000/playlist/home')
else:
form=Genreform()
args={}
args.update(csrf(request))
args['form'] = form
return render_to_response('playlists/add_gen.html',args)
please suggest a way to auto fill pub_date

this is the correct code
class Genreform(forms.ModelForm):
pub_date=forms.DateTimeField(widget=forms.HiddenInput(),initial=timezone.now())
class Meta:
model=Genre
fields={ 'gen_name','pub_date'}

Related

passwords is changing for all users in django rest

I have made an API for password change but it's changing the passwords for all users instead of only one user.
seriealizer code is below:
class ChangePasswordSerializer(serializers.ModelSerializer):
password1 = serializers.CharField(write_only=True, required=True, validators=[validate_password])
password2 = serializers.CharField(write_only=True, required=True)
old_password = serializers.CharField(write_only=True, required=True)
class Meta:
model = User
fields = ('old_password', 'password1', 'password2')
def validate(self, attrs):
if attrs['password1'] != attrs['password2']:
raise serializers.ValidationError({"password": "Password fields didn't match."})
return attrs
def validate_old_password(self, value):
user = self.context['request'].user
if not user.check_password(value):
raise serializers.ValidationError({"old_password": "Old password is not correct"})
return value
def update(self, instance, validated_data):
instance.set_password(validated_data['password1'])
instance.save()
return instance
view code is below:
class ChangePasswordView(generics.UpdateAPIView):
queryset = User.objects.all()
permission_classes = (IsAuthenticated,)
serializer_class = ChangePasswordSerializer
what is wrong with this code ?
Password change is very straight forward. Django already has a form to do it. Try the below code:
#api_view(['PUT'])
#permission_classes([IsAuthenticated])
def change_password(request):
form = PasswordChangeForm(request.user, request.data)
if form.is_valid():
form.save()
serializer = UserSerializer(request.user)
return Response(serializer.data)
return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)
Read this page for more information on how to build user auth methods using DRF: https://kushgoyal.com/creating-a-sceure-login-api-using-drf-token-auth/
url for this will be of this format:
url(r'change_password/', views.change_password)

how to use check_password inside validate function?

I have this serializer:
class ChangePasswordSerializer(DynamicFieldsModelSerializer):
current = serializers.CharField()
confirm = serializers.CharField()
class Meta:
model = models.User
fields = ('password', 'current', 'confirm')
validators = []
def update(self, instance, validated_data):
if instance.check_password(validated_data.get('current')):
instance.set_password(validated_data['password'])
instance.save()
else:
raise serializers.ValidationError("Current password is not correct")
return instance
I have this inside my update function:
instance.check_password(validated_data.get('current'))
but I want this action happens outside of function update in validate_current function, but I dont know how
You can write custom validator for the current password
def validate_current(self, value):
if not self.instance.check_password(value):
raise serializers.ValidationError("Current password is not correct")
return value
you will have to pass instance from view in serializer

Django REST Framework - optimizing nested serialization of a queryset

I have a model and serializer like this:
models.py
class CalendarEvent(BaseMixin):
title = models.TextField(blank=True, null=True)
class CalendarEventReminder(BaseMixin):
event = models.ForeignKey(CalendarEvent, related_name = 'reminders')
minutes = models.CharField()
class Meta:
managed = False
db_table = 'calendar_event_reminder'
def __str__(self):
return self.minutes
serializer.py
class CalendarEventSerializer(serializers.ModelSerializer):
reminders = serializers.StringRelatedField(many=True)
class Meta:
model = CalendarEvent
fields = ('title', 'reminders')
In my view, I do the following:
def test(request):
#...
event = CalendarEvent.objects.filter(id__in = [930, 935])
serializer = CalendarEventSerializer(event, many = True)
print (serializer.data)
#...
When I open the Debug Toolbar, I see that the database hits reminders table twice for each of the calendar events.
The question is, how this behavior could be optimized.
The most straight-forward way would be prefetching the CalendarEventReminders of the CalendarEvents in your view:
# views.py
def get(request):
event = CalendarEvent.objects.filter(id__in = [930, 935]) \
.prefetch_related('reminders')
# ...
This will prefetch all CalendarEventReminders while getting the CalendarEvents.
Note that this will not trigger a sql join like select_related() would do. We can't use select_related() in this case because we're following the relation backwards. :)
Check out the Django Docs regarding prefetch_related.

Passing argument from view to Custom RelatedField serializer

How can I pass an argument to a serializers.RelatedField class from views.py. I need to pass language_id to query Language.objects model within that RelatedField.
I am not sure if I took a right approach to this issue. What I want to achieve is to present information about genres associated to a movie from database model about depending on the language. The MovieGenre model has genre ID field which I want to replace with actual Genre name.
My serialiser.py
class GenreField(serializers.RelatedField):
def to_representation(self, value, language_id=1):
genre_name = GenresVideo.objects.get(genre_id=value, language_id=language_id)
return genre_name.name
class MovieGenresSerializer(serializers.ModelSerializer):
genre_id = GenreField(read_only=True)
class Meta:
model = MoviesGenres
As you see, here I query Language.objects with default value but I would like to pass it from views (language_id).
My views.py:
class MovieGenresTestViewSet(viewsets.ModelViewSet):
lookup_field = 'movie'
queryset = MoviesGenres.objects.all()
serializer_class = MovieGenresSerializer
def list(self, request, language_pk):
queryset = MoviesGenres.objects.all()
serializer = MovieGenresSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, movie, language_pk):
queryset = MoviesGenres.objects.filter(movie=movie)
serializer = MovieGenresSerializer(queryset, many=True)
return Response(serializer.data)
And my urls.py:
router.register(r'lang', LanguagesViewSet, base_name='lang')
mov_gen = routers.NestedSimpleRouter(router, r'lang', lookup='language')
mov_gen.register(r'mg', MovieGenresTestViewSet, base_name='mg')
url(r'^api/', include(genre_spec.urls))
My models.py
class Languages(models.Model):
name = models.CharField(unique=True, max_length=255)
short_name = models.CharField(unique=True, max_length=4, blank=True, null=True)
active = models.BooleanField(default="")
class Meta:
managed = False
db_table = 'languages'
ordering = ('id',)
class GenresVideo(models.Model):
genre_id = models.IntegerField()
language = models.ForeignKey('Languages')
name = models.CharField(max_length=255, blank=True, null=True)
class Meta:
managed = False
db_table = 'genres_video'
unique_together = (('genre_id', 'language'),)
ordering = ('genre_id',)
class MoviesGenres(models.Model):
movie = models.ForeignKey(Movies)
genre_id = models.IntegerField()
class Meta:
managed = False
db_table = 'movies_genres'
unique_together = (('movie', 'genre_id'),)
Through the urls routes, I can get a correct response from API including the language_id. I just need to pass it to the view somehow.
Thanks a lot for help!
I'll try to answer to your first question, with the easiest implementation possible: SerializerMethodField. Because we will get the language id via the context passed to the serializer, we should either generate the context for the serializer, or let the framework do that for us.
Now to the problem at hand: you aren't filtering the queryset (MoviesGenres) by language per se. Thus, we can avoid overwriting the list and retrieve methods. Nevertheless, the router mechanism will inject in kwargs for the view method the language_pk parameter - that's the parameter that we will retrieve from within the serializer context:
class MovieGenresSerializer(serializers.ModelSerializer):
genre = searializers.SerializerMethodField()
class Meta:
model = MoviesGenres
def get_genre(self, instance):
# get the language id from the view kwargs
language_id = self.context['view'].kwargs['language_pk']
# get the genre
try:
genre_name = GenresVideo.objects.get(genre_id=instance.genre_id, language_id=language_id).name
except GenresVideo.DoesNotExist:
genre_name = None
# return the formatted output
return genre_name
class MovieGenresTestViewSet(viewsets.ModelViewSet):
lookup_field = 'movie'
queryset = MoviesGenres.objects.all()
serializer_class = MovieGenresSerializer

Django 1.3 CreateView, ModelForm and filtering fields by request.user

I am trying to filter a field on a ModelForm. I am subclassing the generic CreateView for my view. I found many references to my problem on the web, but the solutions do not seem to work (for me at least) with Django 1.3's class-based views.
Here are my models:
#models.py
class Subscriber(models.Model):
user = models.ForeignKey(User)
subscriber_list = models.ManyToManyField('SubscriberList')
....
class SubscriberList(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=70)
....
Here is my view:
#views.py
class SubscriberCreateView(AuthCreateView):
model = Subscriber
template_name = "forms/app.html"
form_class = SubscriberForm
success_url = "/app/subscribers/"
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
return super(SubscriberCreateView, self).form_valid(form)
Here is my original form for adding a Subscriber, with no filter:
#forms.py
class SubscriberForm(ModelForm):
class Meta:
model = Subscriber
exclude = ('user', 'facebook_id', 'twitter_id')
Here is my modified form, attempting to filter, but doesn't work:
#forms.py
class SubscriberForm(ModelForm):
class Meta:
model = Subscriber
exclude = ('user', 'facebook_id', 'twitter_id')
def __init__(self, user, **kwargs):
super(SubscriberForm, self).__init__(**kwargs)
self.fields['subscriber_list'].queryset = SubscriberList.objects.filter(user=user)
If I change this modified form as so:
def __init__(self, user=None, **kwargs)
It works - It brings me NO subscriber lists. But any way I try to pass the request user, I invariably get a a name "request" or name "self" not defined error.
So, how can I modify my code to filter subscriber_list by the request.user, and still use Django 1.3's CreateView.
I see you've been posting this question in various places.. and the way I found that is because I was trying to figure out the same thing. I think I just got it working, and here's what I did. I overwrote get_form() from FormMixin to filter a specific form fields queryset:
class MyCreateView(CreateView):
def get_form(self, form_class):
form = super(MyCreateView,self).get_form(form_class) #instantiate using parent
form.fields['my_list'].queryset = MyObject.objects.filter(user=self.request.user)
return form

Resources