In Django framework, I have a model like this:
class Employee(models.Model):
organization = models.ForeignKey(Organization, on_delete=models.CASCADE,related_name='organization_user')
added_by = models.ForeignKey(Hr, on_delete=models.CASCADE, related_name='added_user')
email = models.CharField(max_length=30, null=True, blank=True)
phone = models.CharField(max_length=30, null=True, blank=True)
The Employee is not a Django auth user, and I need to save the employee with multiple emails and phone numbers.
I am using the SQLite database it's not having ArrayField as a model option.
Already tried like this :
phon1='9400' (already in db)
phon2='9411' (input number)
phon = phon1 +','+phon2
'9400,9411'
But here is the chance to create duplicate phone numbers.
Then how can I save the employee with multiple fields?
While technically you can have your phone numbers (and emails) as "num1,num2,..." and prevent duplicates, it's not generally a good idea to store them in this way.
The best-practice is something like this:
class Employee(models.Model):
organization = models.ForeignKey(Organization, on_delete=models.CASCADE,related_name='organization_user')
added_by = models.ForeignKey(Hr, on_delete=models.CASCADE, related_name='added_user')
class PhoneNumber(models.Model):
number = models.CharField(max_length=30)
employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
class Email(models.Model):
email = models.EmailField(max_length=30)
employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
Related
Each time i want to add an invoice, i want to have a unique invoice_id which is an increment number (+1), but the problem is that i have a multiple users app, so i get the error that this invoice_id already exist. how can i customize the ids so each user can have its ids following the latest of same user.
class Company(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=64)
class Invoice(models.Model):
company = models.ForeignKey('Company', on_delete=models.CASCADE)
invoice_id = models.CharField(max_length=20, unique=True)
name = models.CharField(max_length=256)
add an last_invoice field in your company record. Then let it do the work for you by adding a function that generates new invoice:
class Company(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=64)
last_invoice = models.CharField(max_length=20)
def get_invoice(self):
l_newNum = self.last_invoice + '1' #your number here
self.last_invoice = l_newNum
self.save()
return l_newNum
class Invoice(models.Model):
company = models.ForeignKey('Company', on_delete=models.CASCADE)
#you no longer need unique as it will create a mess between companies
invoice_id = models.CharField(max_length=20)
name = models.CharField(max_length=256)
def save(self):
self.invoice_id = self.company.get_invoice()
super(Invoice,self).save()
You need to fill in the details here and there, but this should work for you. IDeally I would suggest that the get_invoice is actually used to automatically create Invoice entry for the company, but this would depend on the concrete case you are building.
I'm doing some querying currently and I was wondering if I would be able to query something from these 3 models where the return would give me all the projects the users are working on. I know about the basic filtering however thats not really enough in this case, how would one go about querying through 2 foreign keys.
class User(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.EmailField()
class ProjectUser(models.Model):
project = models.ForeignKey("Project", on_delete=models.CASCADE)
user = models.ForeignKey("User", on_delete=models.CASCADE)
is_lead = models.BooleanField(default=False)
class Meta:
unique_together = (("project", "user"),)
class Project(models.Model):
name = models.CharField(max_length=255)
client = models.CharField(max_length=255)
complete = models.BooleanField(default=False)
You can obtain the Projects a user is working on with:
Project.objects.filter(
projectuser__user=user
)
The double underscores are used to look "through" relations. Furthermore the default related_query_name=… parameter [Django-doc] is, if not specified, the name of the model in lowercase.
I'm working to remove an existing GenericForeignKey relationship from some models. Id like to change it to the Reformatted Model below. Does migrations provide a way to convert the existing content_type and object_ids to the respective new ForeignKey's? (to keep existing data). Basically brand new at programming, so pardon me if I'm asking a stupid question.
class Donation(models.Model):
amount_id = models.CharField(max_length=12, unique=True, editable=False)
date_issued=models.DateField(auto_now_add=True)
description=models.TextField(blank=True, null=True)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type','object_id')
class Individual(BaseModel):
first_name = models.CharField(max_length=50)
middle_name = models.CharField(max_length=50, blank=True,
null=True)
last_name = models.CharField(max_length=50)
suffix = models.CharField(max_length=50, blank=True, null=True)
contributor = generic.GenericRelation(Donation, related_query_name='individual')
class Organization(models.Model):
name = models.CharField(max_length=100)
contributor = generic.GenericRelation(Donation, related_query_name='organization')
Reformatted Model
class Donation(models.Model):
amount_id = models.CharField(max_length=12, unique=True, editable=False)
date_issued=models.DateField(auto_now_add=True)
description=models.TextField(blank=True, null=True)
contributor_group = models.ForeignKey(Organization, null=True, blank=True, on_delete=models.CASCADE)
contributor_individual = models.ForeignKey(Individual, null=True, blank=True, on_delete=models
Based on your model definition of Donation Model, one of fields contributor_group , contributor_model will always be Null post migration.
I hope you have taken that into you consideration.
Just to be safe Do this in two phases.
1. Keep the content_type and object_id and add the two new fields.
2. Next step remove the generic fields post data population.
There are two ways to populate those new fields
Django migrations provides you a way to populate new fields with values during the migrations. You can look it up. I haven't done that before either.
For more control and some learning as well. You can populate that via scripting as well. You can setup django-extensions module in your project. And write a script to do that population for you as well. A sample script would look like.
from myproject.models import Donation, Individual, Organization
from django.contrib.contenttypes.models import ContentType
def run():
organization_content_type = ContentType.objects.get_for_model(Organization)
individual_content_type = ContentType.obejcts.get_for_model(Individual)
donations = Donation.objects.all()
for donation in donations:
if donation.content_type_id == organization_content_type.id:
donation.contributor_group = donation.object_id
elif donation.content_type_id == individual_content_type.id:
donation.contributor_individual = donation.object_id
else:
print "Can't identify content type for donation id {}".format(donation.id)
donation.save()
Check the values are correct and then remove the generic fields.
Facing some issues with formatting here.
This is the scenario: I have a form with many field filled with some his own data and the user can change them.
In this form I collect 3 kind of data:
the first type of data are user data,
the second type of data are user personal data and
the third type of data are user work data.
Work data and personal data are binding to user data using a foreign key.
When the user clicks submit, my view collect this data from the request and send them to a view.
This is the problem:
this 3 type of data already have a model and a modelform (I used it in another part of this website),
class User(models.Model):
username = models.CharField(max_length=30, unique=True)
password = models.CharField(max_length=30)
email = models.EmailField(unique=True)
confirmed = models.BooleanField(default=False)
class PersonalData(models.Model):
user = models.OneToOneField(AtgUser, primary_key=True)
name = models.CharField(max_length=100)
surname = models.CharField(max_length=100)
address = models.CharField(max_length=200, blank=True)
class WorkData(models.Model):
user = models.OneToOneField(AtgUser, primary_key=True)
companyname = models.CharField(max_length=100)
And their related modelforms:
class Form1(ModelForm):
class Meta:
model = user.User
class Form2(ModelForm):
class Meta:
model = user.PersonalData
exclude = 'user'
class Form3(ModelForm):
class Meta:
model = user.WorkData
exclude = 'user'
But now I must use a new form that includes all the data like this:
class Bigform(Forms.form):
username = models.CharField(max_length=30, unique=True)
password = models.CharField(max_length=30)
email = models.EmailField(unique=True)
name = models.CharField(max_length=100)
surname = models.CharField(max_length=100)
address = models.CharField(max_length=200, blank=True)
companyname = models.CharField(max_length=100)
so:
When I get my request in the view, How can I extract part of the collected data in Bigform and put this data in their own modelform or model in order to update this data in my Database?
I thought of extract some field from Bigform in order to fill an already exist model or model form.
Is this the correct way?
Suggestions?
Thanks in advance
I have an Event model. Events can have many 'presenters'. But each presenter can either 1 of 2 different types of profiles. Profile1 and Profile2. How do I allow both profiles to go into presenters?
This will be 100% backend produced. As to say, admin will be selecting "presenters".
(Don't know if that matters or not).
class Profile1(models.Model):
user = models.ForeignKey(User, null=True, unique=True)
first_name = models.CharField(max_length=20, null=True, blank=True)
last_name = models.CharField(max_length=20, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
about = models.TextField(null=True, blank=True)
tags = models.ManyToManyField(Tag, null=True, blank=True)
country = CountryField()
avatar = models.ImageField(upload_to='avatars/users/', null=True, blank=True)
score = models.FloatField(default=0.0, null=False, blank=True)
organization = models.CharField(max_length=2, choices=organizations)
class Profile2(models.Model):
user = models.ForeignKey(User, null=True, unique=True)
first_name = models.CharField(max_length=20, null=True, blank=True)
last_name = models.CharField(max_length=20, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
about = models.TextField(null=True, blank=True)
tags = models.ManyToManyField(Tag, null=True, blank=True)
country = CountryField()
avatar = models.ImageField(upload_to='avatars/users/', null=True, blank=True)
score = models.FloatField(default=0.0, null=False, blank=True)
...
class Event(models.Model):
title = models.CharField(max_length=200)
sub_heading = models.CharField(max_length=200)
presenters = ManyToManyField(Profile1, Profile2, blank=True, null=True) ?
...
# I've also tried:
profile1_presenters = models.ManyToManyField(Profile1, null=True, blank=True)
profile2_presenters = models.ManyToManyField(Profile2, null=True, blank=True)
# is there a better way to accomplish this?...
I think you have a desing problem here. In my opinion, you must think what is a Presenter and what's the different between a Presenter with "profile 1" and with "profile 2". What are you going to do with this models? Are you sure there are just two profiles? Is there any chance that, in some time from now, a different profile ("profile 3") appears? And profile 4? and profile N?
I recommend you to think again about your models and their relations. Do NOT make this decision thinking of how difficul/easy will be to handle these models from django admin. That's another problem and i'll bet that if you think your models a little bit, this won't be an issue later.
Nevertheless, i can give you some advice of how to acomplish what you want (or i hope so). Once you have think abount how to model these relations, start thinking on how are you going to write your models in django. Here are some questions you will have to answer to yourself:
Do you need one different table (if you are going to use SQL) per profile?
If you cannot answer that, try to answer these:
1) What's the difference between two different profiles?
2) Are there more than one profile?
3) Each presenter have just one profile? What are the chances that this property changes in near future?
I don't know a lot about what you need but i think the best option is to have a model "Profile" apart of your "Presenter" model. May be something like:
class Profile(models.Model):
first_profile_field = ...
second_profile_field = ...
# Each presenter have one profile. One profile can "represent"
# to none or more presenters
class Presenter(models.Model):
first_presenter_field = ....
second_presenter_field = ....
profile = models.ForeignKey(Profile)
class Event(models.Model):
presenters = models.ManyToManyField(Presenter)
....
This is just an idea of how i imagine you could design your model. Here are some links that may help you once you have design your models correctly and have answered the questions i made to you:
https://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance
https://docs.djangoproject.com/en/dev/misc/design-philosophies/#models
http://www.martinfowler.com/eaaCatalog/activeRecord.html
And to work with the admin once you decide how your design will be:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/
EDIT:
If i'm not wrong, the only difference between profile 1 and 2 fields is the "organization" field. Am i right? So i recommend you to merge both models since they are almost the same. If they have different methods, or you want to add different managers or whatever, you can use the proxy option of django models. For example, you can do this:
class Profile(models.Model):
#All the fields you listed above, including the "organization" field
class GoldenProfile(models.Model):
#you can define its own managers
objects = GoldenProfileManager()
....
class Meta:
proxy = True
class SilverProfile(models.Model):
....
class Meta:
proxy = True
This way, you can define different methods or the same method with a different behaviour in each model. You can give them their own managers, etcetera.
And the event class should stay like this:
class Event(models.Model):
title = models.CharField(max_length=200)
sub_heading = models.CharField(max_length=200)
presenters = ManyToManyField(Profile, blank=True, null=True)
Hope it helps!