I am working on a django admin based project now i am stuck with a big thing.i want to add a field named "item_issued" in the user_profile model.
in the "item issued" field there is a table which consist of 3 column "item_name","quantity" and "price".I am unable to apply this.Can u guys please help me in this?
Thanks in advance
If I understand you correctly you want to add a ForeignKey to your user_profile pointing to item_issued. You can accomplish that by creating a new model ItemIssued with the fields you mentioned:
class ItemIssued(models.Model):
item_name = models.CharField(max_length=100)
quantity = models.IntegerField()
price = models.FloatField()
Now, when you're having ItemIssued model you can add a ForeignKey to user_profile (I assume the model is called UserProfile):
class UserProfile(models.Model):
... # your existing fields
item_issued = models.ForeignKey(ItemIssued)
After that, don't forget to run
python manage.py makemigrations app
python manage.py migrate
Here is a starting point:
models.py:
class ItemIssued(models.Model):
item_name = models.CharField(max_length=50)
quantity = models.IntegerField()
models.DecimalField(max_digits=6, decimal_places=2) #use decimal field for price values.
class UserProfile(models.Model):
# some other fields..
issued_items = models.ManyToManyField("ItemIssued", related_name="+issued_items", null=True, blank=True)
And if you need to use this field outside of Django Admin, views.py:
user = UserProfile.objects.get(username="ali")
new_issued_item = ItemIssued.objects.get(item_name="test_item")
user.issued_items.add(new_issued_item) #add
user.issued_items.delete(new_issued_item) #delete
items = user.issued_items.all() # get all issued items of user
i didn't test the code. But they should work.
Related
I tried to add a field to my ManyToMany relationship models in Django.
So step by step, I created the new model and apply makemigrations and migrate.
I checked I have the new table in my postgresql database.
Now before I will add the through keyword in the ManyToMany field I want to write a function in the migration file that will copy the old data of the previous ManyToMany table to the new one with the additional field.
I followed a solution explained here:
Django migration error :you cannot alter to or from M2M fields, or add or remove through= on M2M fields
I want to test the function that will migrate the data in a test function but I don't understand what to do.
here my code:
survey/models:
class Survey(BaseModel):
name = models.CharField(max_length=256, help_text='Survey name')
user = models.ManyToManyField(User, blank=True, help_text='patient')
survey/models:
class SurveyStatus(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
survey_status = models.CharField(max_length=10,
blank=True,
null=True,
choices=STATUS_SURVEY_CHOICES,
)
The function I wrote that need to copy the data from the previous M2M to the new one is the following one:
def create_through_relations(apps, schema_editor):
Survey = apps.get_model('survey', 'Survey')
SurveyStatus = apps.get_model('survey', 'SurveyStatus')
for survey in Survey.objects.all():
for user in survey.user.all():
SurveyStatus(
user=user,
survey=survey,
survey_status='active'
).save()
I don't understand what is apps? because it is not recognized by python
I don't understand why i need schema_editor because it's not used
it doesn't recognized my Survey or SurveyStatus models too
when i tried to run this script with
if __name__ == "__main__":
create_through_relations(survey)
I've got this error
NameError: name 'survey' is not defined
and if i tried this function
from django.apps import apps
def create_through_relations():
Survey = apps.get_model('survey', 'Survey')
SurveyStatus = apps.get_model('survey', 'SurveyStatus')
for survey in Survey.objects.all():
for user in survey.user.all():
SurveyStatus(
user=user,
survey=survey,
survey_status='active'
).save()
when i tried to run this script with
if __name__ == "__main__":
create_through_relations()
I've got this error
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.
If someone can help and explain me how to solve.thanks
1: Apps represent the different parts of your project (Django Apps)
2: You don't need it at this point. In general, it translates the models into SQL syntax.
3: python manage.py <...> does load the models for execution. Your file is trying to access data that isn't available that way.
4: The variable survey can't be found in python's main function, since you never declared it there. You need to trigger it inside your project.
5: You can test things by creating a test.py (Django Tests)
6: You don't need to transfer the data to a whole new table after changing a model, just extend the existing one and migrate the changes:
class BaseModel(models.Model):
created = models.DateTimeField('created', default=timezone.now)
changed = models.DateTimeField('changed', default=timezone.now, blank=True, null=True)
class Survey(BaseModel):
uuid = models.UUIDField(primary_key=False, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=256, help_text='Survey name')
description = models.TextField('description', blank=True)
status = models.BooleanField(default=False) # paused/ active
class SurveyQuestion(BaseModel):
survey = models.ForeignKey(Survey, related_name='survey', on_delete=models.CASCADE)
text = models.CharField(max_length=256)
# 1 -> Text, # Integer, # ChoiceField, etc.
requested_result = models.IntegerField(default=0)
class QuestionResult(BaseModel):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
question = models.ForeignKey(SurveyQuestion, related_name='survey_question', on_delete=models.CASCADE)
answer = models.CharField(default='', max_length=256)
I am changing the primary key of the legacy database. I was able to change the primary key by setting id as the primary key.
Before
class User(models.Model):
name = models.CharField(max_length=5)
email = models.CharField(max_length=5)
age = models.CharField(max_length=5)
After
class User(models.Model):
id = models.BigIntegerField(primary_key=True)
name = models.CharField(max_length=5)
email = models.CharField(max_length=5)
age = models.CharField(max_length=5)
Then
python manage.py makemigrations
python manage.py migrate
This is working fine.
But I also want to change the default primary key of the tables created via ManyToMany feild.
User Model
class User(models.Model):
id = models.BigIntegerField(primary_key=True)
name = models.CharField(max_length=5)
email = models.CharField(max_length=5)
age = models.CharField(max_length=5)
UserProfile Model
class UserProfile(models.Model):
id = models.BigIntegerField(primary_key=True)
address = models.CharField(max_length=5)
father_name = models.CharField(max_length=5)
pincode = models.CharField(max_length=5)
user = models.ManyToManyField(User)
The ManytoMany field creates table called User_user_userprofile with id as Autofield basically previous or default django primary key.
id, user_id, userprofile_id
ManytoMany Table
Now, How to change the primarykey of ManytoMany Feild ie id created by Django?
PS:
Django: 1.11
Python: 2.7.5
DB: Sqlite3 3.7.17 2013-05-20
I stumbled upon this problem today, and ended up solving it by using the through argument of the ManyToManyField. I solved it for Django v3.2.6 however, but the documentation for v1.11 mentions the same behavior for the same argument, so hopefully the solution should work for your version of Django too. Here's the link to the documentation for v1.11 ManyToManyField.through
What the through argument allows you to do is to create the intermediary table (created automatically by ManyToManyField) yourself. You get finer control of how the intermediary table should look like, what fields it should have and what their behavior should be. Hope you are getting a picture.
Let me give you the example of the problem I faced and how I solved it. Hopefully that will make this clearer.
I was trying to establish a many-to-many relationship between two of my existing models.
My first model looks like this,
class BanglaWords(models.Model):
class Meta:
verbose_name_plural = 'Bangla Words'
bng_id = models.CharField(max_length=16, primary_key=True)
bangla_word = models.CharField(max_length=64)
def __str__(self):
return self.bangla_word
and the second one looks like,
class EnglishWords(models.Model):
class Meta:
verbose_name_plural = 'English Words'
eng_id = models.IntegerField(primary_key=True)
word = models.CharField(max_length=64)
bangla_word = models.ManyToManyField(BanglaWords)
def __str__(self):
return self.word
But this resulted in an intermediary table wordnet_englishwords_bangla_word which looked like this,
wordnet_englishwords_bangla_word
id
englishwords_id
banglawords_id
But I didn't want this, I wanted bng_id to be the pk for this table. I solved the problem with ManyToManyField.through as follows,
I defined the intermediary model(table) myself and with the through argument, I pointed to the new intermediary model I created and instructed django to create the table the way I wanted it.
First I created the intermediary model,
class BanglaEnglishRelations(models.Model):
class Meta:
verbose_name_plural = 'Bangla English Relations'
bng_id = models.OneToOneField('BanglaWords', primary_key=True, on_delete=models.CASCADE)
eng_id = models.ForeignKey('EnglishWords', on_delete=models.CASCADE)
which defines bng_id as the primary key as I desired.
Second, I told the ManyToManyField in EnglishWords to base the table on BanglaEnglishRelations like,
bangla_word = models.ManyToManyField(BanglaWords, through=BanglaEnglishRelations)
This resulted in the table wordnet_banglaenglishrelations which looked like,
wordnet_banglaenglishrelations
bng_id_id
eng_id_id
and surved my purposes. You can do something similar to solve your problem and promote whatever field to a pk.
I'm currently trying to setup some database models in djangos ORM. however im unable to figure out how i'm supposed to reference another models many-to-many- field.
Project model
class Project(models.Model):
projectName = models.CharField(max_length=200)
users = models.ManyToManyField(get_user_model())
projectOwner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='projectowner', default=1)
The users = models.manytomanyfield(get_user_mode()) works fine
and generates the correct relation in the database.
now i want to add a new model that adds a many to many relation between rights and project_user
so what the end result tables are supposed to look like:
project:
projectname - string
projectowner - id of referenced user
user: django orm auth user model
rights:
name
description
etc
project_user:
id
project_id
user_id
rights_projectuser:
id
rights_id
project_user_id
now that last one (rights_projectuser) is what i dont know how to make.
You need to turn "project_user" into a through model that you can then add the many to many relationship to.
class Project(models.Model):
projectName = models.CharField(max_length=200)
users = models.ManyToManyField(get_user_model(), through='ProjectUser')
class ProjectUser(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
rights = models.ManyToManyField(Right)
i now get the following problem when running this code:
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Project(models.Model):
projectName = models.CharField(max_length=200)
users = models.ManyToManyField(get_user_model(), through='ProjectUser')
projectOwner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='projectowner', default=1)
class Right(models.Model):
name = models.CharField(max_length=200)
description = models.CharField(max_length=1000)
class ProjectUser(models.Model):
user_id = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
project_id = models.ForeignKey(Project, on_delete=models.CASCADE)
rights = models.ManyToManyField(Right)
ValueError: Cannot alter field wspingpong.Project.users into wspingpong.Project.users - they are not compatible types (you cannot alter to or from M2M fields, or add or remove through= on M2M fields)
I need to add job offers section to my company site (as a intro to django for me). The problem is that when i inherit my model from mezzanine's Page model it adds to admins create form all bunch of field which i dont need (like publish dates, draft field, comment field etc). I want to make create/edit job offers form as simple as possible.
I tried to inherit it from basic models.Model but it throws an error ...
Unknown column 'project_joboffer.id' in 'field list'"
I tried to customize Admin Form but im still getting error above.
models.py
class JobOffer(models.Model):
title = models.CharField(max_length=255, null=False, blank=False)
place = models.CharField(max_length=255, null=True, blank=True)
date = models.DateTimeField(auto_now_add=True)
content = models.TextField(blank=False,null=False)
published = models.BooleanField(default=True)
deleted = models.NullBooleanField()
forms.py
from django import forms
from ckeditor.widgets import CKEditorWidget
from models import JobOffer
class JobOfferForm(forms.ModelForm):
title = forms.CharField(max_length=255, required=True)
place = forms.CharField(max_length=255, required=False)
content = forms.CharField(required=True , widget=CKEditorWidget())
published = forms.BooleanField(initial=True)
deleted = forms.NullBooleanField()
# class Meta:
# model = JobOffer
admin.py
class JobOfferAdmin(admin.ModelAdmin):
form = JobOfferForm
admin.site.register(JobOffer, JobOfferAdmin)
OK, i fixed it. Migrations creating and deleting wasnt enough. I dont know why but this time i had to also delete entry in django_migrations table.
This is the model I am working with:
from django.db import models
from django.conf import settings
from products.models import Variation
class CartItem(models.Model):
cart = models.ForeignKey('Cart')
items = models.ForeignKey(Variation)
quantity = models.PositiveIntegerField(default=1)
def __unicode__(self):
return self.items.title
class Cart(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
items = models.ManyToManyField(Variation, through='CartItem')
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
def __unicode__(self):
return (str(self.id))
I had run makemigrations and migrate once before, with the items field in the model Cart being items = models.ManyToManyField(CartItem)
Now after making this change, I get the following error:
ValueError: Cannot alter field carts.Cart.items into carts.Cart.items - they are not compatible types (you cannot alter to or from M2M fields, or add or remove through= on M2M fields)
How do I fix this ? Please help.
Like the error says, you can't convert a many-to-many into a foreign key. You'll have to split this into two migrations: first, remove the original field completely and run makemigrations to create the DROP COLUMN call; then, add the foreign key and run makemigrations again to create the ADD COLUMN.