I have a model that looks like this in my application:
class Member(models.Model):
name = models.CharField(max_length=200)
telephone_number = models.CharField(max_length=200)
email_address = models.CharField(max_length=200)
membership_type = models.CharField(max_length=1, choices=MEMBERSHIP_TYPES)
membership_number = models.CharField(max_length=200, primary_key=True)
def __unicode__(self):
return self.name
Reading up on forms for my model i see that i can replace the models stuff with forms and place it in my forms.py. However when for membership type i don't know how it is used in the forms class.
Hmmm... You might want to read on ModelForms.
Using the multiple choice field in the forms class.
Related
I am trying to import data from an csv file into a django db using django-import-export. My problem is trying to upload data with a ForeignKey as an object. I have migrated, followed docs, and still no solution. You can see my error below in the django admin:
Here is my csv data with a blank 'Id' column:
models.py
from django.db import models
from django.shortcuts import reverse
from urllib.parse import urlparse
class States(models.Model):
name = models.CharField(max_length=96, blank=False, unique=True)
abbrv = models.CharField(max_length=2, null=True, blank=True)
class Meta:
ordering = ['name']
verbose_name = 'State'
verbose_name_plural = 'States'
def __str__(self):
return f'{self.name}'
class Person(models.Model):
last_name = models.CharField(
max_length=255, help_text="Enter your last name.")
first_name = models.CharField(
max_length=255, help_text="Enter your first name or first initial.")
address = models.CharField(
max_length=255, blank=True, help_text="Enter your street address.")
city = models.CharField(
max_length=255, blank=True, help_text="Enter your city.")
state = models.ForeignKey('States', to_field='name', on_delete=models.SET_NULL, null=True)
zipcode = models.CharField(max_length=50)
website = models.URLField(
max_length=255, blank=True)
profession = models.CharField(max_length=50, blank=True)
# META CLASS
class Meta:
verbose_name = 'Person'
verbose_name_plural = 'Persons'
ordering = ['last_name', 'first_name']
# TO STRING METHOD
def __str__(self):
"""String for representing the Model object."""
return f'{self.last_name}, {self.first_name}'
admin.py:
from django.contrib import admin
from .models import Person, States
from import_export.admin import ImportExportModelAdmin
from import_export.widgets import ForeignKeyWidget
from import_export import fields, resources
class PersonResource(resources.ModelResource):
state = fields.Field(
column_name='state',
attribute='state',
widget=ForeignKeyWidget(States, 'name'))
class Meta:
model = Person
class PersonAdmin(ImportExportModelAdmin):
list_display = ('last_name', 'first_name', 'state')
search_fields = ('first_name', 'last_name' )
resources_class = PersonResource
admin.site.register(Person, PersonAdmin)
admin.site.register(States)
I think you need to specify both in your question here, as well as to Django how you want the id field treated.
Do you want it propagated with the Django id or pk (sometimes the same sometimes not)? Then you would have id=self.id or id=self.pk somewhere in your view for the datatable.
Do you want your database to create a unique key?
You would need to add some functionality someplace to tell Django how to fill in that field.
Also, if you want it to create an id different from the Django id or pk then you would need to add the field to your model.
https://docs.djangoproject.com/en/3.1/ref/forms/validation/
https://docs.djangoproject.com/en/3.1/ref/validators/
https://docs.djangoproject.com/en/3.1/ref/forms/api/
Or, perhaps after Validation of the form, when you create the object. Add something to the effect of id=[database function to create unique id].
Another solution might be a templateTag or templateFilter to create a value on the form side if you want to create the id based on info contained in the form. Like combining last 4 of name with time of submission.
https://docs.djangoproject.com/en/3.1/ref/templates/builtins/
https://docs.djangoproject.com/en/3.1/howto/custom-template-tags/
Having just re-read your question, also, I'm not sure but you might be asking if the database can support an embedded reference to another object. Is ID a reference to another model's key? That's a whole different question. And it is database specific.
Last Suggestion: Perhaps a re-read of:
https://docs.djangoproject.com/en/3.1/ref/forms/fields/#fields-which-handle-relationships
This error is occur because your id did not received an id or int value it received a str type of value Wyoming try to pass int value in id
Update
just update your PersonResource Meta class like this
class PersonResource(resources.ModelResource):
state = fields.Field(
column_name='state',
attribute='state',
widget=ForeignKeyWidget(States, 'name'))
class Meta:
model = Person
import_id_fields = ['id']
The default field for object identification is id, you can optionally
set which fields are used as the id when importing
check official doc. for more information.
I'm creating a simple contacts app in django and I want to allow everyone to have more than a single phone number.
My models.py looks like this:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
birthday = models.DateField(null=True, blank=True)
def __str__(self):
return ' '.join([self.first_name, self.last_name])
class Phone(models.Model):
phone_number = models.CharField(max_length=12)
description = models.CharField(max_length=25)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
def __str__(self):
return self.phone_number
I need to create a form where I can add the core contact info and as many phone numbers as wanted.
I have a ModelForm like
class PersonForm(forms.ModelForm):
class Meta:
model = Person
fields = '__all__'
How do I create a phone_number field which allows to insert the phone number?
Here is a nice tutorial that is perhaps a bit more helpful than the documentation if you're struggling:
http://whoisnicoleharris.com/2015/01/06/implementing-django-formsets.html
It goes through using formsets which allow you to have and use more than one form of the same type on a page.
And also shows you a JQuery plugin that allows you to add and remove forms dynamically.
I am having some trouble in selecting data in Django.
models.py
class Location(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
my_location = models.CharField(max_length=120, choices=LOCATION_CHOICES)
update_date = models.DateField(auto_now=True, null=True)
date = models.DateField()
def __str__(self):
return self.my_location
class UserProfile(models.Model):
user = models.ForeignKey(User)
user_base = models.CharField(max_length=120, choices=LOCATION_CHOICES)
user_position = models.CharField(max_length=120)
user_phone = models.PositiveIntegerField()
slug = models.SlugField()
def save(self, *args, **kwargs):
self.slug = slugify(self.user)
super(UserProfile, self).save(*args, **kwargs)
def __unicode__(self):
return self.user.username
views.py
def index(request):
locations = Location.objects.order_by('-update_date')
context = {'locations': locations}
return render(request, 'index.html', context)
I was able to show the email from User module but what I really want to show is the data from UserProfile.
Please, any advice.
Thank you.
Instead of using
user = models.ForeignKey(User)
use:
user = models.OneToOneField(User)
One-to-one relationships suit better your case. If you use them, your User model will automatically get a userprofile attribute that you can use like this:
>>> user = User.objects.get(...)
>>> user.userprofile.user_phone
12345
You can also consider writing a custom User model, so that you can get rid of UserProfile.
Bonus tip: PositiveIntegerField is not the right field for a phone number. Leading zeroes have a meaning. Also, PositiveIntegerField have a maximum value. Use CharField instead.
Use a OneToOneField
To make it more direct, I'd make the UserProfile have a OneToOneField relationship with User, instead of a ForeignKey. Because this will mean that a given user can only have one profile.
class Location(models.Model):
user = models.OneToOneField(User)
In which case you can access it easier with location.user.userprofile.your_field
Using a custom MyUser model
If you want to make this even more direct, you could make a custom MyUser model that will contain both the fields from User and UserProfile.
It would go roughly like this:
from django.contrib.auth.models import AbstractBaseUser
class MyUser(AbstractBaseUser):
# Adding your custom fields
user_base = models.CharField(max_length=120, choices=LOCATION_CHOICES)
user_position = models.CharField(max_length=120)
user_phone = models.CharField(max_length=120)
slug = models.SlugField()
class Location(models.Model)
user = OneToOneField(MyUser) # Using your custom MyUser model
This allows a more direct access, e.g. location.user.user_phone instead of location.user.userprofile.user_phone
I've only provided pseudocode, please refer to Django documentation
Using a ForeignKey means you may have multiple profiles
In the other case where a user may have multiple user profiles, you then have the burden on you to select which profile to use to pull the relevant data from, because then the relationship would be user.userprofile_set, a set that you will have to filter/index to choose from.
I'm having trouble overriding the formset on a TabularInline inline of a ModelAdmin object in my admin site. I know you're supposed to have a model associated with a TabularInline object, but I'm not sure how to specify this on the form object used to generate the formset. With the code below, I'm getting "'AppAssetInline.formset' does not inherit from BaseModelFormSet."
class AppAssetForm(forms.ModelForm):
model = App.assets.through
primary = forms.BooleanField()
uuid = forms.CharField()
class AppAssetInline(admin.TabularInline):
model = App.assets.through
AssetFormset = formset_factory(AppAssetForm)
formset = AssetFormset
class AppAdmin(admin.ModelAdmin):
inlines = [AppAssetInline,]
The answer to my question didn't have to do with how I was structuring my forms, but rather how I was joining fields on my models. I had the following structure in my models:
class App(models.Model):
package = models.FileField(upload_to=settings.APP_PACKAGE_ROOT)
assets = models.ManyToManyField('AppAsset', blank=True, null=True)
download_count = models.IntegerField(default=0)
class AppAsset(models.Model):
def __unicode__(self):
return self.asset_file.name
notes = models.CharField(max_length=255, null=True, blank=True)
type = models.CharField(max_length=255, null=True, blank=True)
asset_file = models.FileField(upload_to=settings.APP_PACKAGE_ROOT)
What I did was change the structure such that AppAsset now has a foreign key on App for its assets. After that, I could use the TabularInline on the AppAsset model with no problems. Here are the latest source files:
https://github.com/ridecharge/spout/blob/master/Spout/AppDistribution/models.py
https://github.com/ridecharge/spout/blob/master/Spout/AppDistribution/admin.py
You should use django.forms.models.inlineformset_factory instead of formset_factory
I have the following models
class Group(models.Model):
name = models.CharField(max_length=32, unique=True)
class Subgroup(models.Model):
name = models.CharField(max_length=32, unique=True)
group = models.ForeignKey(Group)
class Keywords(models.Model):
name = models.CharField(max_length=32, unique=True)
subgroup = models.ForeignKey(Subgroup)
For each Subgroup I need to manage a list of keywords.
I'm trying to use django forms to automatically display a list (select box) where if I add or remove values to that list and then issue a form.save that it automatically updates the models and data.
How exactly can I do this? Are my models designed properly to allow this?
I think you can create form with MultipleChoiceField:
class MyForm(forms.Form):
to_select = forms.MultipleChoiceField(widget=forms.CheckboxInput, choices=[])
In this case you have to override form`s save method.
Did you try to create model form for subgroup class?
class MyForm(forms.ModelForm):
class Meta():
model=Subgroup