I'm new in Django and I try to find out if saving partial forms are a good practice or not. For example, I have Poll App and Candidate model with four fields: name, surname, targets andbiography. And I have a form where I have to fill all these fields. But if user only finished fill name, surname and targets, but even din't start filling biography field, how can I save his draft to user can finish it later and don't make any security mess?
models.py:
class Candidate(models.Model):
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
biography = models.TextField()
targets = models.CharField(max_length=1000)
forms.py
class CandidateForm(ModelForm):
class Meta:
model = Candidate
fields = [
'name',
'surname',
'biography',
'targets',
]
widgets = {
'biography': forms.Textarea(attrs={'rows': 3})
}
I will be happy to see all ideas.
how can I save his draft to user can finish it later and don't make
any security mess?
You can either save the data to DB if you have designed the models to accept null or blank values, Or you can use Django sessions to temporarily store the form data until the form is completed...
In both case the security is not an issue since just like a DB access the django session data is also stored in a database and not in the browser... and so the end users cannot easily mess with the data...
check the following answer if you would like to know more...
Your problem is here :-
models.py:
class Candidate(models.Model):
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
biography = models.TextField()
targets = models.CharField(max_length=1000)
If you put default='your default value':-
models.py:
class Candidate(models.Model):
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
biography = models.TextField(default=' ')
targets = models.CharField(max_length=1000)
I think this is right what you need
Related
Basically, I have two models: User and Event. An event is always associated with one user.
class User(models.Model):
user_id = models.AutoField(primary_key=True)
username = models.CharField(max_length=255, unique=True)
hashed_password = models.CharField(max_length=255)
class Event(models.Model):
event_id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255)
description = models.TextField(max_length=255, blank=True, default='')
user = models.ForeignKey(User)
And then I have the following form for Event.
class EventForm(forms.ModelForm):
class Meta:
model = Event
fields = ['title', 'description', 'user']
I can succesfully show this form in my template to create an event. I can also associate a user to a form successfully with Select field when the users number are still few.
Now the problem is, when I have 1M users in database, my browser crashes when loading the template. Any idea how to solve this one? I was thinking about using AJAX and then search user that matches the username, but I'd like to hear other better approaches. Thanks!
My Users has phone contact LIST(s) - [3121234567,2121234567,6601234567]
Now, I want each user to be able to store as many LIST as possible. Each List must have a name(or description) attached to them under each USER account. Note: the number of LIST is dependent on Users needs. Example:
Students
[3121234567,2121234567,6601234567]
Club Member
[8101234567,8151234567,8171234567]
Now, how do I store it in a database.
Django User Model
class CustomUser(AbstractBaseUser):
username = models.CharField(max_length=254, unique=True)
first_name = models.CharField(max_length=24)
last_name = models.CharField(max_length=30)
phone = models.CharField(max_length=10)
email = models.EmailField(max_length=128)
street = models.CharField(max_length=128)
city = models.CharField(max_length=128)
state = models.CharField(max_length=2, choices=STATE_CHOICES, default=STATE)
zip_code = models.IntegerField(max_length=5, null=True, blank=True
USERNAME_FIELD = 'email'
REQUIRED_FIELD = ['username', 'first_name', 'last_name', 'phone', 'street', 'city', 'state']
objects = CustomUserManager()
Edit(Added):
I am not looking to create Student or ClubMember models. This name is use to identify the python phone contact list. PhoneAddress one can be labelled(named) as Student for one user but called "Conference Attendant" for another. Each user have different # of Lists.
PhoneAdress PhoneAdress2 PhoneAdress3
[3121234567,2121234567,6601234567] [4121234567,3121234567,6601234567] [7121234567,8121234567,9601234567]
Lemme guess, you're coming from a NoSQL background where the database is a document in a JSON form?
If so, I am sorry, in a Relational Database, used by Django in the likes of PostgreSQL or MySQL, they call something Foreign Keys, and that is your way of storing multiple "Lists" related to a particular field.
If you want many users to store as many lists as possible, you're looking at something like this, roughly speaking:
class myUserModel(models.Model):
# your arbitrary fields here
# then you do something like this:
class Student(models.Model):
user = models.ForeignKey(User)
class clubMember(models.Model):
user = models.ForeignKey(User)
With the above setup, you can add as many Student objects associated to the myUserModel class, so as the clubMember
However, if you wish to use PostgreSQL specifically, as your backend (perhaps as perpetual storage backend), you might find some sense in using Django's support for the ArrayField
And ooh, you might need to extend the Django User Model to add any extra fields easily, unless you're willing to go down the road of a custom User Model.
More info:
Django ForeignKey
This SO answer on 'OneToManyFields', similar to adding multiple items to a single field.
I hope the above helps
Create some models:
class Club(models.Model):
name = models.CharField(max_length=256,blank=True,null=True)
date_open = models.DateField()
class Institution(models.Model):
name = models.CharField(max_length=256,blank=True,null=True)
address = models.CharField(max_length=256,blank=True,null=True)
type = models.CharField(max_length=256,blank=True,null=True) #university, college
Rather than using
class CustomUser(AbstractBaseUser):
username = models.CharField(max_length=254, unique=True)
first_name = models.CharField(max_length=24)
last_name = models.CharField(max_length=30)
use composition in the form of OneOnOneField
class UserProfile(models.Model):
user = models.OneOnOneField(User,blank=True,null=True)
club_member = models.ManyToManyField(Club,blank=True, null=True)
institutions = models.ManyToManyField(Institution,blank=True, null=True) # student in
Once you have this, you will be able to get and add as many institutions and clubs to the lists:
user = User.objects.get(id=user_id)
club = Club.objects.get(id=club_id)
institution = Institution.objects.get(id=institution_id)
user.profile.clubs.add(club)
user.profile.institutions.add(institution)
So to verify if the user is a member of a club
club = user.proile.clubs.get(id=club_id)
and to verify the user is a student in an institution use
institution = user.profile.institutions.get(id=institution_id)
I'm trying to make own form adding object Announcement
models.py:
class Announcement(models.Model):
person = models.ForeignKey('Person')
source = models.CharField(max_length=30)
date = models.DateField(default=datetime.now())
valid_date = models.DateField(null=True,blank=True)
class Person(models.Model):
names = models.ManyToManyField('Name')
birth_date = models.DateField(null=True, blank=True)
class Name(models.Model):
first_name = models.CharField(max_length=50,blank=True)
middle_name = models.CharField(max_length=50, blank=True)
last_name = models.CharField(max_length=50, blank=True)
(It maybe loos weird, but in my concept each Person can have more than one Name, and also the same Name can be assigned to different Persons)
forms.py
from django import forms
from backoffice.models import Announcement
class AnnouncementForm(forms.ModelForm):
class Meta:
model = Announcement
fields = ('person','signature','organisation','source', 'date')
And everything works perfectly but I have to choose Person from selectbox. And it is expected behaviour.
But in my case i'm definetely sure, that person doesn't exists in base (all announcements are for different person for very long time - so i want to change person select box to three fields, and create new person (with new names) everytime I save the announcement.
I think I know how to save many to many, that's why i don't put the views.py, but I don't know how to set the forms.py to get fields.
I tried
class AnnouncementForm(forms.ModelForm):
class Meta:
model = Announcement
fields = ('person__names__first_name','signature','organisation','source', 'date')
but got Unknown field(s) (person__names__first_name) specified for Announcement
person__name__first_name will not really work in the forms, that only works for the django admin
you have to create a custom field for the first name and then create a logic for saving on either
def clean(self):
// logic here
or
def save(self, commit=True):
// put clean data here
announcement_form = super(AnnouncementForm, self).save(commit=False)
announcement_form.save()
So I have a model Member:
class Member(models.Model):
first_name = models.CharField(max_length = 15)
last_name = models.CharField(max_length = 15)
house = models.ForeignKey('House', null = True)
created_on = models.DateTimeField('created on')
user = models.OneToOneField(User, null = True)
and a form to create the model:
class MemberForm(forms.Form):
first_name = forms.CharField()
last_name = forms.CharField()
email_address = forms.EmailField()
My app works where you create a House and specify the number of Members in your house. That's as far as I have working, but I would like it to continue to a new page where it displays an appropriate number of forms (one for each Member), and then creates a Member instance for each with the supplied data. I'm confused as to how I access the data from each form, since they're all technically in the same HTML form. More specifically how I identify what email field goes with which first name field and so on. Any help would be greatly appreciated, thanks.
This is what formsets are for.
Note that creating a member from a memberform would be easier if you used model forms (and model formsets).
I'm trying to create a small app for users to have contacts. I'm using django-profiles as a base for my profiles. Now everything works well until I try to submit the edit contact form and I receive this error.
Cannot assign "<Contact: Contact object>": "Contact.user" must be a "UserProfile" instance.
Being pretty new to Django, I'm not even sure if I'm taking the right approach here. My end goal is for the user to be able to add as many contacts as neccessary.
Any advice is appreciated.
My UserProfile model which extends User looks like:
class UserProfile(models.Model):
#User's Info
user = models.ForeignKey(User, unique=True)
first_name = models.CharField("first name", max_length=30)
last_name = models.CharField("last name", max_length=30)
home_address = models.CharField(max_length=50)
primary_phone = PhoneNumberField()
city = models.CharField(max_length=50)
state = USStateField()
zipcode = models.CharField(max_length=5)
birth_date = models.DateField()
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True)
and my contact model looks like this:
class Contact(models.Model):
user = models.ForeignKey(UserProfile)
contact_description = models.CharField("Relation or Description of Contact", max_length=50, blank=True)
contact_first_name = models.CharField("contact first name", max_length=30)
contact_last_name = models.CharField("contact last name", max_length=30)
contact_primary_phone = PhoneNumberField("contact primary phone number")
contact_secondary_phone = PhoneNumberField("contact secondary phone number",blank=True)
and my view:
def editContact(request, username, object_id=False, template_name='contacts/edit.html'):
user = UserProfile.user
AddContactFormset = inlineformset_factory(UserProfile,Contact, extra=1)
if object_id:
contact=Contact.objects.get(pk=object_id)
else:
contact=Contact()
if request.method == 'POST':
f= ContactForm(request.POST, request.FILES, instance=contact)
fs = AddContactFormset(request.POST, instance=contact)
if fs.is_valid() and f.is_valid():
f.save()
fs.save()
return HttpResponse('success')
else:
f = ContactForm(instance=contact)
fs = AddContactFormset(instance=contact)
return render_to_response(template_name ,{'fs':fs,'f':f,'contact': contact}, context_instance=RequestContext(request))
Basically, django-profiles is for something else - it's just helping to create and manage user profiles across an application.
First of all - you should link Contact models directly to the django.contrib.auth.models.User via ForeignKey. This way you can access given User's contacts by a simple query ie. User.contact_set.all() - it will return to you a list of User's contacts. This will also get rid off your error.
Second - fields like first_name, last_name are already definied in django.contrib.auth.models.User, so there is no need to define them again in UserProfile. Read the source of User model here
Third - if your user can only have one Profile and you're not intend to use very old versions of django then you should be using OneToOneField instead of ForeignKey.
Fourth thing - you could probably omit usage of RequestContext() by using one of the generic views bundled with django - read about that here
Last thing - remember that main model for handling the Users is the User model itself. Any custom Profile is just an extension, so link everything which is related to the User to the User model itself.
Happy coding!
To elaborate on bx2's answer, your Contact model should look more like this:
class Contact(models.Model):
user = models.ForeignKey(User, related_name='contacts')
contact_description = models.CharField("Relation or Description of Contact", max_length=50, blank=True)
contact_first_name = models.CharField("contact first name", max_length=30)
contact_last_name = models.CharField("contact last name", max_length=30)
contact_primary_phone = PhoneNumberField("contact primary phone number")
contact_secondary_phone = PhoneNumberField("contact secondary phone number",blank=True)
Your view, frankly, does not make much sense. In general an inline formset is meant to represent records related to some parent record. In your case, it would be the user record, with the contacts being the "children" records. But having both a Contact form and an AddContactFormset doesn't make a lot of sense.
Also, I'd recommend against using variable names like f and fs in Django. Apart from variables like indexes, counters, etc. it doesn't serve any purpose to use short 1-2 character variable names. Go ahead and use longer variable names like form and formset, or even contact_form and contact_formset. It makes it much, much easier to debug the code in the future.