Django forms, saving non-user submitted data - python

class SomeModel(models.Model):
text = models.TextField()
ip = models.IPAddressField()
created_on = models.DateTimeField()
updated_on = models.DateTimeField()
Say I have that as a model, what if I wanted to only display 'text' field widget for the user to submit data, but I obviously wouldn't want the user to see the widgets for ip,created_on, updated_on to be changed. Yes I know I can add it as a hidden field for the form, but that's not what I'm looking for.
I'm more wondering how can I not render those fields at all when rendering my form, and just dynamically populating the fields when a form is posted and pass form validation? I'm guessing to somehow override the blank values of ip,created_on,updated_on while the form is being cleaned/validated. I know how to do this in the view by using request.POST.copy and injected my values, but I'd like to know if it's possible in models or forms.

Two things:
First ModelForms:
Class SomeModelForm(ModelForm):
class Meta:
exclude = ['ip','created_on', 'updated_on']
Two Model Fields API:
class SomeModel(models.Model):
text = models.TextField()
ip = models.IPAddressField()
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
Three:
For ip, i think you should to that in your views.

Related

Specific Queryset for Input on Django ModelAdmin Change Form

I've got a 'Registration' object in place that users can create on the front end without issue.
It looks like this:
class Registration(models.Model):
person = models.ForeignKey(Person, on_delete=models.PROTECT)
course_detail = models.ForeignKey(CourseDetail, on_delete=models.PROTECT)
camp_shirt = models.ForeignKey(CampShirt, on_delete=models.PROTECT)
comments = models.CharField(max_length=200, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return "%s" % (self.course_detail.course.camp)
When I am in the admin and click on a given Registration - it takes a while to load because there are thousands and thousands of Person objects.
For ease of use - there will never be a time when we would need to edit the 'person' associated with a given registration, so I would like to make the 'person' dropdown only show the selected user in the person queryset when editing from the django admin.
So when I go to http://myapp.com/admin/registration/23/change I want the form to only display the currently selected person as the only option in the dropdown.
My admin model looks like this:
class RegistrationAdmin(admin.ModelAdmin):
list_display = ("person", "course_detail")
class Meta:
# I think this is what I do in order to override the default admin form? Not sure.
form = RegistrationAdminForm
My RegistrationAdminForm looks like this:
class RegistrationAdminForm(forms.ModelForm):
# course_detail, person, camp_shirt, comments
person = forms.ModelChoiceField(queryset=Person.objects.filter(
id=registration.person.id)
)
def __init__(self, registration, *args, **kwargs):
super(RegistrationAdminForm, self).__init__(*args, **kwargs)
self.fields['person'].queryset = Person.objects.filter(
id=registration.person.id
)
class Meta:
model = Registration
fields = '__all__'
Main Question : How do I change the admin form so that a specific queryset is returned for one of the fields in the django admin?
If the person field will never be changed you can add the person field to readonly_fields, a select with all Person objects will not be rendered.
class RegistrationAdmin(admin.ModelAdmin):
list_display = ("person", "course_detail")
readonly_fields = ("person", )
Then you do not need your custom form. FYI when you want to add a custom form to a ModelAdmin you do not put it in Meta, you define it on the form itself
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm

How to save two related entries in a single form

I am new to Django and I am creating a simple 2 page messageboard app (submit page and messageboard page)
I am struggling with the form for my submit page. As I am learning my way around Django I decided not to use the standard user model and opted to rather create a model (Poster) which has a one to one relationship with the message model.
Basically in one form I would like to add a message and a poster(foreign key) which has multiple fields.
Is it possible to achieve what I am trying to do?
Thanks in advance for the help.
I don't really know what to try or what to look for. I have included some code below.
Models
class Poster(models.Model):
full_name = models.CharField(max_length = 50)
phone_number = models.CharField(max_length = 15)
email = models.EmailField()
class Message(models.Model):
message_text = models.CharField(max_length=10000)
created_at = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(Poster, on_delete=models.CASCADE)
class MessageForm(forms.ModelForm):
class Meta:
model = Message
fields = ['full_name', 'phone_number', 'email', 'message_text']
Your mistake is trying to use a ModelForm subclass which is for creating or updating one object (database row) only.
Use a plain forms.Form with the fields you want. You'll have to explicitly code them as CharField, EMailField, etc. Then in form_valid (assuming your view is a FormView) you will do something like
poster = Poster()
poster.full_name = form.cleaned_data['full_name']
# ditto for phone_number and email
poster.save()
message = Message( user=poster,
message_text = form.cleaned_data['message_text'] )
message.save()

How can I filter a ManyToManyField against the current User in the Browsable API in DRF?

I have 2 models, Todo and a Tag. Todo has a ManyToMany relationship with Tag. When adding new Todos from the Browsable API, I want to be able to see only the Tags added by the current user as the available options in the multiselect. Currently, it shows all the added Tags, irrespective of who added them. I want to limit the options to only show the Tags added by the current user. (Authentication is setup already)
The models:
class Todo(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
due_at = models.DateTimeField(blank=True)
updated_at = models.DateTimeField(auto_now=True)
tags = models.ManyToManyField(Tag, related_name='todos')
creator = models.ForeignKey(User, on_delete=models.CASCADE, related_name='todos')
class Tag(models.Model):
name = models.CharField(max_length=20)
creator = models.ForeignKey(User, on_delete=models.CASCADE, related_name='created_tags')
def __str__(self):
return self.name
The Serializer:
class TodoCreateSerializer(serializers.ModelSerializer): #This is the one being used for a POST
class Meta:
model = models.Todo
fields = ('title', 'description', 'due_at', 'tags')
Is there some serializer field or some other way to specify which queryset to use in the Serializer? Is there another better approach?
In your TodoCreateSerializer you need to add PrimaryKeyRelatedField with a custom queryset that has the filtered tags of a user.
First, you will need to create a custom PrimaryKeyRelatedField that filter any objects to get only those who owned by the user.
class UserFilteredPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
def get_queryset(self):
request = self.context.get('request', None)
queryset = super(UserFilteredPrimaryKeyRelatedField, self).get_queryset()
if not request or not queryset:
return None
return queryset.filter(user=request.user)
(This is a generic one and can be used when filtering in objects by user)
Then you should use this one in you TodoCreateSerializer:
class TodoCreateSerializer(serializers.ModelSerializer):
tags = UserFilteredPrimaryKeyRelatedField(queryset= Tag.objects, many=True)
class Meta:
model = models.Todo
fields = ('title', 'description', 'due_at', 'tags')

How to save forms field in django

i have some fields in my django models.
class Product(models.Model):
user=models.ForeignKey(User)
product_name = models.CharField(max_length=50)
product_cost = models.IntegerField(default=0,null=True, blank=True)
product_description = models.TextField(null=True, blank=True)
quantity = models.IntegerField(default=0,null=True, blank=True)
product_image = models.FileField(upload_to='images/',blank=True,null=True,)
coupon_code = models.CharField(max_length=50)
time = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.product_name or u''
when i use form to save all the data from front end in my database i can do this.
class DocumentForm(forms.ModelForm):
class Meta:
model = Product
fields = ('user','product_name','product_image','product_cost','product_description','product_description','coupon_code')
Problem is this i don't want to allow user to fill user data from front-end.when user save data it save request.user to user.
I am new to work with forms so facing some issues.
Please help me how can i do this.
Thanks in advance.
In fields you have to remove user:
so it will look like this:
class DocumentForm(forms.ModelForm):
class Meta:
model = Product
fields = ('product_name','product_image','product_cost','product_description','product_description','coupon_code')
and in your views.py when you save the data from the form you have write something like this:
user = request.user
in this case user will be saved if he is authenticated.
If you want that not authenticated user could fill the form too, you have to change in your model.py Product class from:
user=models.ForeignKey(User)
to:
user=models.ForeignKey(User, null=True)
then not authenticated user will be NULL.

Django forms with Foreign keys

I have scenario in which a user can have multiple books. I can create two different models for user and books and relate them using foreign keys (or one-to-many will be right way ?).
I have created a django forms for User model but when i do like this {{form.as_p}} in templates only user model fields is shown not books field.
I want that with user fields my books model filed also displayed (like book names field more then once because he can have multiple books) , Please let me know if it is possible using django forms/models or I have to user simple html forms with jquery and then save data in models.
Thanks
EDIT:
my models :
class Product(models.Model):
categories = models.CharField(max_length=5, choices = settings.CATEGORIES)
name = models.CharField(max_length=100)
description = models.TextField()
currency = models.CharField(max_length=5, choices = settings.CURRENCY)
status = models.BooleanField(default=True)
def __unicode__(self):
return self.name
class Prices(models.Model):
products = models.ForeignKey(Product)
prices = models.IntegerField()
def __unicode__(self):
return self.id
if you are creating a form for Prices, try putting this in your model form:
products = forms.ModelMultipleChoiceField(queryset=Product.objects.all())
I think you should add required fields in meta class such as
class ThreadForm(ModelForm):
class Meta:
model = Thread
fields = ('Books', 'User')
Please understand the work flow to use foreign keys in model form here.

Categories