Django Forms query - python

I have created a app using the following Model
models.py
class Vendor(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.name
class Model(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.name
class Request(models.Model):
job_reference = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.job_reference
class Device(models.Model):
Vendor = models.ForeignKey('Vendor')
Model = models.ForeignKey('Model')
device_id = models.CharField(max_length=255, unique=True, blank=True)
is_encrypted = models.BooleanField()
is_medical = models.BooleanField()
request_job_reference = models.ForeignKey('Request')
submitted = models.DateTimeField(default=timezone.now)
When i go to the admin page I can add new devices which displayed each of the fields and the "Vendor" and "Model" allows me to either select an existing entry or has a plus icon to add a new entry (which is great)
Django_Admin_form
When i create a form for my app
forms.py
from django import forms
from . models import Device
class AddDevice(forms.ModelForm):
class Meta:
model = Device
fields = ('Vendor', 'Model', 'device_id', 'is_encrypted', 'is_medical', 'submitted')
The form on my webpage display ok however there is no option to insert a new entry to "Vendor" or "Model".
Webpage Form
I have looked on other posts on here as users have had the same issue and it's been suggested to use "ModelChoiceField" but unfortunately it still doesn't make any sense to me. Either i'm completely missing something or I have setup my models in a way which is making things harder for myself.
Can anyone explain how I can go about doing this?

Related

Field 'id' expected a number - Uploading ForeignKey to django-import-export

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.

Show all users related to tenant in one place

I'm working on an application in the saas model (django 2.1). I use the django tenants plugin (https://github.com/tomturner/django-tenants).
My problem is to display all tenants in the "public" schema. In such a way as to see how much each tenant has users, to be able to manage them, etc.
Is it a good architectural solution to put a foreign key into Tenant in the User model and save this column during the registration process?
Is there another way to do it?
Below is example, pseudo code:
class Tenant(TenantMixin):
name = models.CharField(_('Name of company'), max_length=50, unique=True)
on_trial = models.BooleanField(default=True)
paid_until = models.DateTimeField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
auto_create_schema = True
def __str__(self):
return self.name
def get_name(self):
return self.name
class Domain(DomainMixin):
pass
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('Email address'), unique=True)
first_name = models.CharField(_('First name'), max_length=60, blank=True)
last_name = models.CharField(_('Last name'), max_length=60, blank=True)
member_of_company = models.ForeignKey(Tenant, on_delete=models.CASCADE, related_name='users', null=True, blank=True)
You can iterate over your tenants and get the Users for each tenant with the following code:
from django.db import connection
from django.contrib.auth import get_user_model
from tenant_schemas.utils import get_tenant_model
UserModel = get_user_model()
TenantModel = get_tenant_model()
for tenant in TenantModel.objects.all():
connection.set_tenant(tenant)
tenant_users = UserModel.objects.all()
# Do whatever you want with your users

In Django can I use get absolute url with if statements to refer to other apps?

Can I use get_absolute_url with if statements to refer to other apps?
Another django newbie question:
My django project has a customer model that I'd like to share across multiple products that are each contained in an app (e.g. mobile, fixed).
Currently, I have this customer model within the mobile app:
# mobile/models.py
class Client(models.Model):
client_code = models.CharField(max_length=6, unique=True, db_index=True,)
company_name = models.CharField(max_length=200, blank=False, null=False)
slug = models.SlugField(db_index=True, unique=True, max_length=200)
def get_absolute_url(self):
return reverse('mobile:mobile_list_by_client',args=[self.slug])
The absolute url yields a path e.g.: '127.0.0.1:8000/mobile/AAA001' to customer AAA001.
This is the mobile product model in the mobile app:
# mobile.models.py
class MobileLineIdentifiers(models.Model):
client_code_1 = models.ForeignKey(Client, related_name = 'client_mobile' )
mtn = models.CharField(max_length=11, blank=False, null=False, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, unique=True)
def get_absolute_url(self):
return reverse('mobile:mtn_detail', args=[self.id, self.slug])
I have Client as foriegn key in the fixed app:
# fixed/models.py
from mobile.models import Client
class FixedLineIdentifiers(models.Model):
client_code_3 = models.ForeignKey(Client, related_name = 'client_fixed' )
fixed_cli = models.CharField(max_length=11, blank=False, null=False, db_index=True)
def get_absolute_url(self):
return reverse('fixed:fixed_detail', args=[self.id, self.slug])
Can I simply re-use the mobile client model across apps using 'if' statements within the get_absolute_url function?
What I'd like to achive:
# mobile/models.py
class Client(models.Model):
#....
def get_absolute_url(self):
# IF mobile:
return reverse('mobile:mobile_list_by_client',args=[self.slug])
# IF fixed:
return reverse('fixed:fixed_list_by_client',args=[self.slug])
I'm struggling with the 'if' statement references. How do I distinguish between mobile and fixed references here?
Thank you.
You can follow the foreign keys backwards using self.client_mobile and self.client_fixed. You use these names because you have set related_name in your foreign keys. See the related objects reference docs for more info:
def get_absolute_url(self):
if self.client_mobile.exists():
return reverse('mobile:mobile_list_by_client',args=[self.slug])
elif self.client_fixed.exists():
return reverse('fixed:fixed_list_by_client',args=[self.slug])
else:
# return fallback

How to create a contact form allowing to add multiple phone numbers in django

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.

Ordering mptt tree using a field

This is the original category model:
class Category(MPTTModel):
name = models.CharField(max_length=50, unique=True)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
def __unicode__(self):
return self.name
class MPTTMeta:
order_insertion_by = ['name']
Then I needed to order the category, so I altered it like the following:
class Category(MPTTModel):
name = models.CharField(max_length=50, unique=True)
order = models.SmallIntegerField() <<<<<<<<<
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
def __unicode__(self):
return self.name
class MPTTMeta:
order_insertion_by = ['order'] <<<<<<<<<
And I changed the Django admin declaration from:
admin.site.register(Category, MPTTModelAdmin)
To:
class CategoryAdmin(MPTTModelAdmin):
list_display = ('name', 'order')
list_editable = ('order',)
admin.site.register(Category, CategoryAdmin)
Then everything fall apart after making a few edits from the admin control panel. I can't describe exactly what happened but it seems the lft, rght, level and parent_id where messed up by these changes.
Am I using order_insertion_by in the wrong context? Is it for something else? I tried to search the docs but didn't get a useful answer.
I faced this problem. The problem is not in the package django-mptt, and in the framework Django, more precisely in the admin. Perhaps this is due to several administrators working simultaneously. While only one solution - to abandon the list_editable in admin class or write a script with the same field order for Ajax.
In order to restore the tree, use rebuld method: Category.tree.rebuild()

Categories

Resources