how to bind two models in django - python

please help a beginner. I'm trying to build a poll app in Django and I want to change my admin panel so that I can change and add questions and choices in the same page iv already tried to create a new model and bind the question and choice model together but didn't work please help me.
this is my models.py inside my poll app and another problem I have is that I want to have different numbers of choices for different questions but I don't know how to write
from django.db import models
# Create your models here.
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
class Bind(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
add_question =Question(question_text=question_text,pub_date=pub_date)
choice_text_1= models.CharField(max_length=200,default='yes')
votes_1= models.IntegerField(default=0)
choice_text_2= models.CharField(max_length=200,default='yes')
votes_2= models.IntegerField(default=0)
choice_text_3= models.CharField(max_length=200,default='yes')
votes_3= models.IntegerField(default=0)
choice_text_4= models.CharField(max_length=200,default='yes')
votes_4= models.IntegerField(default=0)
add_choice1=Choice(choice_text=choice_text_1,votes=votes_1)
add_choice2=Choice(choice_text=choice_text_2,votes=votes_2)
add_choice3=Choice(choice_text=choice_text_3,votes=votes_3)
add_choice4=Choice(choice_text=choice_text_4,votes=votes_4)
def __str__(self):
return self.question_text
return self.choice_text
and this is my admin panel id like to change it that I can add question with different number of choices and when I save I can find save question in question model pannel and choices in the choice model panel please help me I'm a beginner
enter image description here
and this is views.py file:
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
return Question.objects.order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {'question': question,'error_message': "You didn't select a choice.",})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
and the error by executing the python manage.py migrate
C:\projects\AM\FM\mysite>python manage.py migrate Operations to
perform: Apply all migrations: admin, auth, contenttypes, polls,
sessions Running migrations: Applying
polls.0009_auto_20200914_1002...Traceback (most recent call last):
File
"C:\projects\AM\FM\lib\site-packages\django\db\models\fields_init_.py",
line 1774, in get_prep_value
return int(value) ValueError: invalid literal for int() with base 10: 'choice'
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File "manage.py", line 22, in
main() File "manage.py", line 18, in main
execute_from_command_line(sys.argv) File "C:\projects\AM\FM\lib\site-packages\django\core\management_init_.py",
line 401, in execute_from_command_line
utility.execute() File "C:\projects\AM\FM\lib\site-packages\django\core\management_init_.py",
line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv) File "C:\projects\AM\FM\lib\site-packages\django\core\management\base.py",
line 330, in run_from_argv
self.execute(*args, **cmd_options) File "C:\projects\AM\FM\lib\site-packages\django\core\management\base.py",
line 371, in execute
output = self.handle(*args, **options) File "C:\projects\AM\FM\lib\site-packages\django\core\management\base.py",
line 85, in wrapped
res = handle_func(*args, **kwargs) File "C:\projects\AM\FM\lib\site-packages\django\core\management\commands\migrate.py",
line 243, in handle
post_migrate_state = executor.migrate( File "C:\projects\AM\FM\lib\site-packages\django\db\migrations\executor.py",
line 117, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial) File
"C:\projects\AM\FM\lib\site-packages\django\db\migrations\executor.py",
line 147, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial) File
"C:\projects\AM\FM\lib\site-packages\django\db\migrations\executor.py",
line 227, in apply_migration
state = migration.apply(state, schema_editor) File "C:\projects\AM\FM\lib\site-packages\django\db\migrations\migration.py",
line 124, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state) File
"C:\projects\AM\FM\lib\site-packages\django\db\migrations\operations\fields.py",
line 104, in database_forwards
schema_editor.add_field( File "C:\projects\AM\FM\lib\site-packages\django\db\backends\sqlite3\schema.py",
line 328, in add_field
self.remake_table(model, create_field=field) File "C:\projects\AM\FM\lib\site-packages\django\db\backends\sqlite3\schema.py",
line 189, in remake_table
self.effective_default(create_field) File "C:\projects\AM\FM\lib\site-packages\django\db\backends\base\schema.py",
line 303, in effective_default
return field.get_db_prep_save(self.effective_default(field), self.connection) File
"C:\projects\AM\FM\lib\site-packages\django\db\models\fields\related.py",
line 971, in get_db_prep_save
return self.target_field.get_db_prep_save(value, connection=connection) File
"C:\projects\AM\FM\lib\site-packages\django\db\models\fields_init.py",
line 823, in get_db_prep_save
return self.get_db_prep_value(value, connection=connection, prepared=False) File
"C:\projects\AM\FM\lib\site-packages\django\db\models\fields_init.py",
line 2388, in get_db_prep_value
value = self.get_prep_value(value) File "C:\projects\AM\FM\lib\site-packages\django\db\models\fields_init.py",
line 1776, in get_prep_value
raise e.class( ValueError: Field 'id' expected a number but got 'choice'.

You cannot directly assign other models to other model's fields. You have to use either ForeignKey (One Object To Many Referrable Objects) or ManyToManyField (Many Objects Can Be Contained To This Object).
At this point, you might want to consider making class Bind to class Questionnaire since you're combining them.
With that, with fixes applied and redundancies, this should be the final code (for inheritances only!)
class Question(models.Model):
question_text = models.CharField(max_length=200)
question_choices = models.ForeignKey("Choice", on_delete=models.CASCADE)
pub_date = models.DateTimeField(help_text='date published', auto_now_add=True)
def __str__(self):
return self.question_text
# No need to refer to the `Question` Model unless you have something to do important.
# Cross-Reference is okay, but its redundant unless special handling is required (for instance, you want pure integrity of ownership of this object, etc. But its quite hard to manage if your models were scaling.)
class Choice(models.Model):
# question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
class Questionnaire(models.Model):
questions = models.ManyToManyField("Question", blank=True)
pub_date = models.DateTimeField(help_text='date published', auto_now_add=True)
def __str__(self):
return self.question_text
NOTES:
If you read the changes closely, you might see yourself, why I assigned the object in "str" form? That's because Django was able to load objects, even or after the one who requires it. Meaning, You don't need to put another object on the top to refer at, but rather, just put it in str reference even the object is placed anywhere and you're good to go.
Note that in DateTimeField, you would want to consider auto_now_add=True, it automatically handles the time where this object has been saved for the first time.
I want to make all choices under Question. This would be nice because if you want to make a question, there's a field available for you to create a choice to.
I changed Bind with Questionnaire for clarity. This should be enough to see the relationship or inheritance to your model.
I used ManyToManyField to set number of questions (or objects) to this Questionnaire.

Usually, in such cases, you don't need to create "Bind" model. You just need to add "sequence" integer field into your Choice model. Then, each question can have infinite number of choices, for example:
Choice.objects.create(question=question1, sequence=0)
Choice.objects.create(question=question1, sequence=1)
Choice.objects.create(question=question1, sequence=2)...

Related

Django TabularInline error in the admin.py file

Hey guys i have been trying to create an inline TabularInline view of the my model in the django admin.py file. I am facing an issue where i am getting the following error in the code below.
Exception in thread django-main-thread:
Traceback (most recent call last):
File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/usr/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "/home/brian/Desktop/django react learning /site/lib/python3.8/site-packages/django/utils/autoreload.py", line 53, in wrapper
fn(*args, **kwargs)
File "/home/brian/Desktop/django react learning /site/lib/python3.8/site-packages/django/core/management/commands/runserver.py", line 118, in inner_run
self.check(display_num_errors=True)
File "/home/brian/Desktop/django react learning /site/lib/python3.8/site-packages/django/core/management/base.py", line 442, in check
raise SystemCheckError(msg)
django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:
ERRORS:
<class 'tweets.admin.TweetlikeAdmin'>: (admin.E202) 'tweets.Tweet' has no ForeignKey to 'tweets.Tweet'.
So at first I thought I had missed something but when I tried changing it I got more errors which really don't make sense. so I made sure I share with you my models.py file and my admin.py file
here is my models.py file
class Tweetlike(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
tweet = models.ForeignKey('Tweet',on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
class Tweet(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE) #this means that one user can own tweets
likes = models.ManyToManyField(User,related_name='tweet_user', blank=True, through=Tweetlike)
content = models.TextField(blank=True,null=True)
timestamp = models.DateTimeField(auto_now_add=True)
image = models.FileField(upload_to='images/',blank=True,null=True)
def __str__(self):
return self.content
and lastly here is the admin.py file. this is where the error is coming from when i tried running the server
class TweetlikeAdmin(admin.TabularInline):
model = Tweet
class TweetAdmin(admin.ModelAdmin):
inlines = [TweetlikeAdmin,]
list_display = ['__str__','user']
search_fields = ['content','user__username', 'user__email']
class Meta:
model = Tweet
admin.site.register(Tweet,TweetAdmin)
You've not set the correct model, you've got them both pointing at the Tweet model. Change the inline model;
class TweetlikeAdmin(admin.TabularInline):
model = Tweetlike

Wagtail error new models.CharField in models.py

I hope you're all well :) Could you please help me. I'm a beginner. I'm launching a new website with python and I choose wagtail for the CMS. I'd like to change the model of each blog_page in order to have more information on it. But I'm running into some issues :(
Everything was working with this code (blog/models.py) :
from django.db import models
from django import forms
from modelcluster.fields import ParentalKey, ParentalManyToManyField
from wagtail.core.models import Page, Orderable
from wagtail.core.fields import RichTextField, StreamField
from wagtail.core import blocks
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, MultiFieldPanel, TabbedInterface, ObjectList, StreamFieldPanel
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.images.blocks import ImageChooserBlock
from wagtail.search import index
from modelcluster.contrib.taggit import ClusterTaggableManager
from taggit.models import TaggedItemBase
from wagtail.snippets.models import register_snippet
class BlogIndexPage(Page):
intro = RichTextField(blank=True)
content_panels = Page.content_panels + [
FieldPanel('intro', classname="full")
]
class BlogPageTag(TaggedItemBase):
content_object = ParentalKey(
'BlogPage',
related_name='tagged_items',
on_delete=models.CASCADE
)
class BlogPage(Page):
date = models.DateField("Post date")
intro = models.CharField(max_length=250)
body = RichTextField(blank=True)
recette = RichTextField(blank=True)
aliment = RichTextField(blank=True)
forcealiment = RichTextField(blank=True)
tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
categories = ParentalManyToManyField('blog.BlogCategory', blank=True)
def main_image(self):
gallery_item = self.gallery_images.first()
if gallery_item:
return gallery_item.image
else:
return None
search_fields = Page.search_fields + [
index.SearchField('intro'),
index.SearchField('body'),
index.SearchField('recette'),
index.SearchField('aliment'),
index.SearchField('forcealiment'),
]
content_panels = Page.content_panels + [
MultiFieldPanel([
FieldPanel('date'),
FieldPanel('tags'),
FieldPanel('categories', widget=forms.CheckboxSelectMultiple),
], heading="Blog information"),
FieldPanel('intro'),
FieldPanel('body'),
FieldPanel('recette'),
FieldPanel('aliment'),
FieldPanel('forcealiment'),
InlinePanel('gallery_images', label="Gallery images"),
]
class BlogPageGalleryImage(Orderable):
page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='gallery_images')
image = models.ForeignKey(
'wagtailimages.Image', on_delete=models.CASCADE, related_name='+'
)
caption = models.CharField(blank=True, max_length=250)
panels = [
ImageChooserPanel('image'),
FieldPanel('caption'),
]
class BlogTagIndexPage(Page):
def get_context(self, request):
# Filter by tag
tag = request.GET.get('tag')
blogpages = BlogPage.objects.filter(tags__name=tag)
# Update template context
context = super().get_context(request)
context['blogpages'] = blogpages
return context
#register_snippet
class BlogCategory(models.Model):
name = models.CharField(max_length=255)
icon = models.ForeignKey(
'wagtailimages.Image', null=True, blank=True,
on_delete=models.SET_NULL, related_name='+'
)
panels = [
FieldPanel('name'),
ImageChooserPanel('icon'),
]
def __str__(self):
return self.name
class Meta:
verbose_name_plural = 'blog categories'
But when I try to add a new field 'cooker' like
cooker = models.CharField(max_length=250)
First stel is okay :
(monProjetWagtail:3.7)[dulo0814#louisiane monProjetWagtail]$ python manage.py makemigrations
Migrations for 'blog':
blog/migrations/0018_auto_20200522_1106.py
- Remove field autobio from blogpage
- Add field cooker to blogpage
Second step is not okay :(
(monProjetWagtail:3.7)[dulo0814#louisiane monProjetWagtail]$ python manage.py migrate
System check identified some issues:
WARNINGS:
?: (mysql.W002) MySQL Strict Mode is not set for database connection 'default'
HINT: MySQL's Strict Mode fixes many data integrity problems in MySQL, such as data truncation upon insertion, by escalating warnings into errors. It is strongly recommended you activate it. See: https://docs.djangoproject.com/en/3.0/ref/databases/#mysql-sql-mode
Operations to perform:
Apply all migrations: admin, auth, blog, contenttypes, home, sessions, taggit, wagtailadmin, wagtailcore, wagtaildocs, wagtailembeds, wagtailforms, wagtailimages, wagtailredirects, wagtailsearch, wagtailusers
Running migrations:
Applying blog.0013_blogpage_autorpost...Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
utility.execute()
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/core/management/__init__.py", line 395, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/core/management/base.py", line 328, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/core/management/base.py", line 369, in execute
output = self.handle(*args, **options)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/core/management/base.py", line 83, in wrapped
res = handle_func(*args, **kwargs)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/core/management/commands/migrate.py", line 233, in handle
fake_initial=fake_initial,
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/migrations/executor.py", line 117, inmigrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/migrations/executor.py", line 147, in_migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/migrations/executor.py", line 245, inapply_migration
state = migration.apply(state, schema_editor)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/migrations/migration.py", line 124, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/migrations/operations/fields.py", line 112, in database_forwards
field,
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/backends/mysql/schema.py", line 80, in add_field
super().add_field(model, field)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/backends/base/schema.py", line 450, in add_field
definition, params = self.column_sql(model, field, include_default=True)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/backends/base/schema.py", line 223, in column_sql
default_value = self.effective_default(field)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/backends/base/schema.py", line 303, in effective_default
return field.get_db_prep_save(self._effective_default(field), self.connection)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 821,in get_db_prep_save
return self.get_db_prep_value(value, connection=connection, prepared=False)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/django/db/models/fields/__init__.py", line 816,in get_db_prep_value
value = self.get_prep_value(value)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/wagtail/core/fields.py", line 111, in get_prep_value
return json.dumps(self.stream_block.get_prep_value(value), cls=DjangoJSONEncoder)
File "/home/dulo0814/virtualenv/monProjetWagtail/3.7/lib/python3.7/site-packages/wagtail/core/blocks/stream_block.py", line 260,in get_prep_value
return value.get_prep_value()
AttributeError: 'datetime.datetime' object has no attribute 'get_prep_value'
(monProjetWagtail:3.7)[dulo0814#louisiane monProjetWagtail]$
Can someone help me please :)?
Ps: I'm french
The error message shows that the error is on the migration 0013_blogpage_autorpost, not the 0018_auto_20200522_1106 migration you just created. Presumably you weren't running ./manage.py migrate after every makemigrations step (or you would have seen this error earlier).
The error is referring to a StreamField - it looks like you had a datetime object where there should have been a block. As there aren't any StreamFields in your models now, I guess this is a field that you added and subsequently removed (but it's still part of the migration history). My recommendation would be to delete all of the migration files in blog/migrations numbered 0013 and above, and then re-run ./manage.py makemigrations so that you have a new migration sequence without that error. (Normally, deleting migrations isn't a good idea, as it means that your database might end up in a state that doesn't match the code - but in this case I believe it should be safe, as the migrations from 0013 onward haven't been run yet.)

Django Error (Attribute): 'CharField' object has no attribute 'is_related'

I am trying to make a description to every user, in my new project. But i get an error when i try to makemigrations. I do not know how to fix it.
I have tried different things but nothing worked, my coding is maybe very bad, but i am also new to python and django.
The Error:
C:\Users\bruger\Dropbox\min-login-web\web_login>python manage.py makemigrations
Traceback (most recent call last):
File "manage.py", line 15, in <module>
execute_from_command_line(sys.argv)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from_command_line
utility.execute()
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\__init__.py", line 375, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\base.py", line 316, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\base.py", line 353, in execute
output = self.handle(*args, **options)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\base.py", line 83, in wrapped
res = handle_func(*args, **kwargs)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\core\management\commands\makemigrations.py", line 143, in handle
loader.project_state(),
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\migrations\loader.py", line 322, in project_state
return self.graph.make_state(nodes=nodes, at_end=at_end, real_apps=list(self.unmigrated_apps))
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\migrations\graph.py", line 378, in make_state
project_state = self.nodes[node].mutate_state(project_state, preserve=False)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\migrations\migration.py", line 87, in mutate_state
operation.state_forwards(self.app_label, new_state)
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\migrations\operations\models.py", line 85, in state_forwards
list(self.managers),
File "C:\Users\bruger\AppData\Local\Programs\Python\Python37\lib\site-packages\django\db\migrations\state.py", line 377, in __init__
if field.is_relation and hasattr(field.related_model, '_meta'):
AttributeError: 'CharField' object has no attribute 'is_relation'
My Models file:
from django import forms
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from PIL import Image
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
def save(self):
super().save()
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
class Desc(models.Model):
description = forms.CharField(widget = forms.Textarea, max_length = 250, required=False)
def __str__(self):
return f'{self.user.username} Desc'
I Hope somebody can help me, because this is really getting on my nerves.
You mixed forms and models. A model does not specify a (HTML) form, it specifies how the database should store data, so you need to use a models.CharField:
class Desc(models.Model):
description = models.CharField(max_length=250)
Such CharField has no widget assigned to it, this is something you should handle at the form level.
You probably will need to make migrations, since up to this point, there was no description field in your Desc model.
I agree to some extent that it is confusing that the forms have frequently a field with the same name (well those typically are the default form fields for the model field with the same name). The idea is however that model fields specify the columns in a database, whereas form fields specify text boxes, check boxes, etc. in a (HTML) form.

django.db.utils.IntegrityError: (1062, "Duplicate entry '' for key 'slug'")

I'm trying to follow the tangowithdjango book and must add a slug to update the category table. However I'm getting an error after trying to migrate the databases.
http://www.tangowithdjango.com/book17/chapters/models_templates.html#creating-a-details-page
I didn't provide a default value for the slug, so Django asked me to provide one and as the book instructed I type in ''.
It's worth noticing that instead of using sqlite as in the original book I'm using mysql.
models.py
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
views = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Category, self).save(*args, **kwargs)
class Meta:
verbose_name_plural = "Categories"
def __unicode__(self):
return self.name
class Page(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=128)
url = models.URLField()
views = models.IntegerField(default=0)
def __unicode__(self):
return self.title
The command prompt
sudo python manage.py migrate
Operations to perform:
Apply all migrations: admin, rango, contenttypes, auth, sessions
Running migrations:
Applying rango.0003_category_slug...Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 377, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **options.__dict__)
File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 338, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python2.7/dist-packages/django/core/management/commands/migrate.py", line 160, in handle
executor.migrate(targets, plan, fake=options.get("fake", False))
File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/executor.py", line 63, in migrate
self.apply_migration(migration, fake=fake)
File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/executor.py", line 97, in apply_migration
migration.apply(project_state, schema_editor)
File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/migration.py", line 107, in apply
operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/operations/fields.py", line 37, in database_forwards
field,
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/mysql/schema.py", line 42, in add_field
super(DatabaseSchemaEditor, self).add_field(model, field)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/schema.py", line 411, in add_field
self.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/schema.py", line 98, in execute
cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 81, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/mysql/base.py", line 128, in execute
return self.cursor.execute(query, args)
File "/usr/local/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 205, in execute
self.errorhandler(self, exc, value)
File "/usr/local/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
django.db.utils.IntegrityError: (1062, "Duplicate entry '' for key 'slug'")
Let's analyse it step by step:
You're adding slug field with unique = True, that means: each record must have different value, there can't be two records with same value in slug
You're creating migration: django asks you for default value for fields that exists already in database, so you provided '' (empty string) as that value.
Now django is trying to migrate your database. In database we have at least 2 records
First record is migrated, slug column is populated with empty string. That's good because no other record is having empty string in slug field
Second record is migrated, slug column is populated with empty string. That fails, because first record already have empty string in slug field. Exception is raised and migration is aborted.
That's why your migration fails. All you should do is to edit migration, copy migrations.AlterField operation twice, in first operation remove unique=True. Between that operations you should put migrations.RunPython operation and provide 2 parameters into that: generate_slugs and migrations.RunPython.noop.
Now you must create inside your migration function BEFORE migration class, name that function generate_slugs. Function should take 2 arguments: apps and schema_editor. In your function put at first line:
Category = apps.get_model('your_app_name', 'Category')
and now use Category.objects.all() to loop all your records and provide unique slug for each of them.
If you have more than one category in your table, then you cannot have unique=True and default='', because then you will have more than one category with slug=''. If your tutorial says to do this, then it's bad advice, although it might work in SQLite.
The correct approach to add a unique field to a model is:
Delete your current migration that isn't working.
Add the slug field, with unique=False. Create a new migration and run it.
Set a unique slug for every category. It sounds like the rango populate script might do this. Alternatively, you could write a migration to set the slugs, or even set them manually in the Django admin.
Change the slug field to unique=True. Create a new migration and run it.
If that's too difficult, then you could delete all your categories from your database except one. Then your current migration will run without having problems with the unique constraint. You can add the categories again afterwards.
You must have rows in your table already with empty slugs, which is a violation of the mysql unique constraint you created. You can update them manually by running manage.py dbshell to get to the mysql client, then updating the offending rows, e.g.
update table rango_category set slug = name where slug = '';
(assuming the rows with blank slugs have names). Or you can delete the rows with
delete from rango_category where slug = '';
After that, you should be able to run your migrations.

Local field clashes with field of similar name

I'm trying to add a new database model that will let me "group" expenses, but am running across this issue when running python manage.py makemigrations
My virtual environment looks like this:
Django==1.7.3
argparse==1.2.1
django-braces==1.4.0
django-chartit==0.1
django-crispy-forms==1.4.0
django-debug-toolbar==1.2.2
psycopg2==2.6
six==1.9.0
sqlparse==0.1.14
wsgiref==0.1.2
Here is the traceback:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/jeff/.virtualenvs/ggc/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/home/jeff/.virtualenvs/ggc/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 377, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/jeff/.virtualenvs/ggc/local/lib/python2.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **options.__dict__)
File "/home/jeff/.virtualenvs/ggc/local/lib/python2.7/site-packages/django/core/management/base.py", line 338, in execute
output = self.handle(*args, **options)
File "/home/jeff/.virtualenvs/ggc/local/lib/python2.7/site-packages/django/core/management/commands/makemigrations.py", line 111, in handle
convert_apps=app_labels or None,
File "/home/jeff/.virtualenvs/ggc/local/lib/python2.7/site-packages/django/db/migrations/autodetector.py", line 42, in changes
changes = self._detect_changes(convert_apps, graph)
File "/home/jeff/.virtualenvs/ggc/local/lib/python2.7/site-packages/django/db/migrations/autodetector.py", line 109, in _detect_changes
self.old_apps = self.from_state.render(ignore_swappable=True)
File "/home/jeff/.virtualenvs/ggc/local/lib/python2.7/site-packages/django/db/migrations/state.py", line 67, in render
model.render(self.apps)
File "/home/jeff/.virtualenvs/ggc/local/lib/python2.7/site-packages/django/db/migrations/state.py", line 316, in render
body,
File "/home/jeff/.virtualenvs/ggc/local/lib/python2.7/site-packages/django/db/models/base.py", line 229, in __new__
'base class %r' % (field.name, name, base.__name__)
django.core.exceptions.FieldError: Local field u'id' in class 'ExpenseGroup' clashes with field of similar name from base class 'Asset
'
This is the model code - I've tried cutting the ExpenseGroup model down to only the groupName as a field but I get the same error. What am I missing?
class Asset(TimeStampedModel):
assetName = models.CharField(max_length=255)
assetAddress = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, blank=True)
class Meta:
unique_together = ('assetName', 'assetAddress')
def __str__(self):
return self.assetName
def save(self, *args, **kwargs):
self.slug = slugify(self.assetName)
super(Asset, self).save(*args, **kwargs)
class ExpenseGroup(TimeStampedModel):
groupName = models.CharField(max_length=255, blank=False)
expenseName = models.ForeignKey(Expense, related_name='expenseGroup')
class Meta:
unique_together = ('expenseName', 'groupName')
def __str__(self):
return self.groupName
def save(self, *args, **kwargs):
return super(ExpenseGroup, self).save(*args, **kwargs)
class Expense(TimeStampedModel):
assetName = models.ForeignKey(Asset, related_name='assetExpense')
category = models.ForeignKey(ExpenseCategory, related_name='expenseCategory')
expensePeriod = models.DateTimeField(blank=False)
expenseName = models.CharField(max_length=255, blank=False)
expenseAmount = models.DecimalField(max_digits=20, decimal_places=2, blank=True)
class Meta:
unique_together = ('expenseName', 'expensePeriod')
def __str__(self):
return self.expenseName
def save(self, *args, **kwargs):
super(Expense, self).save(*args, **kwargs)
Can you post the TimeStampedModel definition? I suspect that you didn't declare the base model as Abstract. That why the "id" fields are conflicted with each others.
class TimeStampedModel(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
It's a bug with Django 1.7.3, upgrade to the latest and you'll be fine (1.7.5 at the time)
There's more to this than what you posted. Can you post your entire models file? or a link to a gist? I'm surprised you are not getting an error about the FK reference to 'Expense' from the 'ExpenseGroup' model, as it's defined later in the file.
Do you have any existing migrations? I would suggest deleting any of your existing migrations and all your pyc files and trying again.

Categories

Resources