Wagtail error new models.CharField in models.py - python

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.)

Related

Django - Can't import other app's model from same directory

I've got a problem with importing model from another app for Foreign key.
I tried two ways to use field from other model:
Import it as a string, it doesn't provide any errors before migrating model:
from_city = models.ForeignKey('cities.City', blank=True,
null=True,
related_name='from_city_set',
on_delete=models.CASCADE)
It provides an error when i'm trying to use "makekigrations" or "migrate" command
Import it as python object, but there is a strange moment. It tries to import 'city' app from src folder like that:
from src.cities.models import City
from_city = models.ForeignKey(City, blank=True,
null=True,
related_name='from_city_set',
on_delete=models.CASCADE
)
Both variants provides the same traceback:
Traceback (most recent call last):
File "C:\TrainProject\src\manage.py", line 22, in <module>
main()
File "C:\TrainProject\src\manage.py", line 18, in main
execute_from_command_line(sys.argv)
File "C:\TrainProject\venv\lib\site-packages\django\core\management\__init__.py", line 446, in execute_from_command_line
utility.execute()
File "C:\TrainProject\venv\lib\site-packages\django\core\management\__init__.py", line 440, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\TrainProject\venv\lib\site-packages\django\core\management\base.py", line 402, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\TrainProject\venv\lib\site-packages\django\core\management\base.py", line 448, in execute
output = self.handle(*args, **options)
File "C:\TrainProject\venv\lib\site-packages\django\core\management\base.py", line 96, in wrapped
res = handle_func(*args, **kwargs)
File "C:\TrainProject\venv\lib\site-packages\django\core\management\commands\makemigrations.py", line 196, in handle
loader.project_state(),
File "C:\TrainProject\venv\lib\site-packages\django\db\migrations\loader.py", line 361, in project_state
return self.graph.make_state(
File "C:\TrainProject\venv\lib\site-packages\django\db\migrations\graph.py", line 329, in make_state
project_state = self.nodes[node].mutate_state(project_state, preserve=False)
File "C:\TrainProject\venv\lib\site-packages\django\db\migrations\migration.py", line 89, in mutate_state
operation.state_forwards(self.app_label, new_state)
File "C:\TrainProject\venv\lib\site-packages\django\db\migrations\operations\models.py", line 724, in state_forwards
state.alter_model_options(
File "C:\TrainProject\venv\lib\site-packages\django\db\migrations\state.py", line 182, in alter_model_options
model_state = self.models[app_label, model_name]
KeyError: ('cities', 'city')
How can i solve it? 'train' app folder in the same place as 'cities' app.
UPD
Installed apps:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'cities',
'trains',]
Models (cities/models and trains/models):
class City(models.Model):
name = models.CharField(max_length=40, unique=True, verbose_name='Название города')
class Train(models.Model):
name = models.CharField(max_length=50, unique=True,
verbose_name='Название поезда')
travel_time = models.PositiveSmallIntegerField(verbose_name='Время в пути')
from_city = models.ForeignKey('cities.City', related_name='from_city_set',
on_delete=models.CASCADE
)
to_city = models.ForeignKey('cities.City', related_name='to_city_set',
on_delete=models.CASCADE
)
trains/models.py should be like this:
from src.cities import models as city_md
class Train(models.Model):
name = models.CharField(max_length=50, unique=True,
verbose_name='Название поезда')
travel_time = models.PositiveSmallIntegerField(verbose_name='Время в пути')
from_city = models.ForeignKey(city_md.City, related_name='from_city_set',
on_delete=models.CASCADE
)
to_city = models.ForeignKey(city_md.City, related_name='to_city_set',
on_delete=models.CASCADE
)
Finally! I've solved this problem:
Delete your DB file
Delete everything from migrations folder in each app except file 'init.py'
Run cmd 'python manage.py makemigrations' and 'python manage.py migrate'
Problem solved!
UPD
It doesn't matter how you import another model to ForeingKey field, it can be a python string or a python object (of course after you imported this model):
from_city = models.ForeignKey('cities.City', related_name='from_city_set',
on_delete=models.CASCADE
)
_______________________________________________________________________
from city.models import City
from_city = models.ForeignKey(City, related_name='from_city_set',
on_delete=models.CASCADE
)

how to bind two models in django

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)...

'NoneType' object has no attribute '_meta' while changing models

I am attempting to restructure my database models to include more data than django.contrib.auth.models.User. However, making the changes to models.py and views.py, then running python manage.py makemigrations doesn't properly update my migrations. Apparently, Django still thinks I'm using a proxy model.
I had to change users/migrations/0001_initial.py to avoid a dependency error, then I ran python manage.py makemigrations and got No changes detected.
users/migrations/0001_initial.py (before changes)
# Generated by Django 2.2 on 2019-05-01 03:13
from django.db import migrations
import users.managers
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0011_update_proxy_permissions'),
]
operations = [
migrations.CreateModel(
name='Person',
fields=[
],
options={
'proxy': True,
'constraints': [],
'indexes': [],
},
bases=('auth.user',),
managers=[
('objects', users.managers.PersonManager()),
],
),
]
users/migrations/0001_initial.py (after changes)
# Generated by Django 2.2 on 2019-05-01 03:13
from django.db import migrations
import users.managers
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = []
users/models.py (before changes)
from django.db import models
from django.contrib.auth.models import User
from . import managers
class Person(User):
objects = managers.PersonManager()
class Meta:
proxy = True
users/models.py (after changes)
from django.db import models
from django.contrib.auth.models import User
from users import managers
class Profile:
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=30)
objects = managers.ProfileManager()
users/views.py
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from users.models import Profile
def index(request):
profile = Profile.objects.get(user_pk=request.session['id']) \
if 'id' in request.session else None
return render(request, 'users/index.html', {
'profile': profile,
})
def login(request):
valid, response = Profile.objects.login_register(request, 'login')
if not valid:
for error in response:
messages.error(request, error)
return redirect('users:index')
profile = Profile.objects.get(pk=response)
messages.success(request, 'Welcome back, %s!' % profile.user.first_name)
request.session['id'] = response
return redirect('users:index')
def register(request):
valid, response = Profile.objects.login_register(request, 'register')
if not valid:
for error in response:
messages.error(request, error)
return redirect('users:index')
messages.success(request, 'You have successfully created an account.')
request.session['id'] = response
return redirect('users:index')
def logout(request):
del request.session['id']
messages.success(request, 'You have successfully logged out.')
return redirect('users:index')
When I try to login or register, I expect the page to reload with the login/registration form changed to the user's profile page.
Error message
Internal Server Error: /profile/
Traceback (most recent call last):
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/matt/Repositories/pharmasseuse/users/views.py", line 12, in index
if 'id' in request.session else None
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/db/models/query.py", line 399, in get
clone = self.filter(*args, **kwargs)
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/db/models/query.py", line 892, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/db/models/query.py", line 910, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1290, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1318, in _add_q
split_subq=split_subq, simple_col=simple_col,
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1190, in build_filter
lookups, parts, reffed_expression = self.solve_lookup_type(arg)
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1049, in solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
File "/home/matt/Repositories/pharmasseuse/env/lib/python3.5/site-packages/django/db/models/sql/query.py", line 297, in get_meta
return self.model._meta
AttributeError: 'NoneType' object has no attribute '_meta'
Any help is appreciated.
I don't think its a good idea to change in migrations files. You can do the changes in model directly, and after changing the model, run ./manage.py makemigrations to generate new migration files.
Also, you need to subclass the model class from models.Model:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=30)
objects = managers.ProfileManager()
Update
(from comments) As your manager has been changed, I think you can proceed with either one of the following solutions:
Keep both ProfileManager and PersonManager in users.manager, then run makemigrations.
Update the migration file like this(remove managers attribute from dictionary):
# Generated by Django 2.2 on 2019-05-01 03:13
from django.db import migrations
import users.managers
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0011_update_proxy_permissions'),
]
operations = [
migrations.CreateModel(
name='Person',
fields=[
],
options={
'proxy': True,
'constraints': [],
'indexes': [],
},
bases=('auth.user',),
# managers=[
# ('objects', users.managers.PersonManager()),
# ],
),
]

Django: dynamic model fields and migrations

I have problems understanding how django's model fields work. What I want to achieve is something like a PriceField (DecimalField), that dynamically creates/injects another model field, let's say a currency (CharField) field.
I have read an interesing blog posts about this topic at https://blog.elsdoerfer.name/2008/01/08/fuzzydates-or-one-django-model-field-multiple-database-columns/. I think (and hope) that I've understood the core messages of the articles. But as most of them are a little bit outdated, I don't know if they are still valid for current django versions and my below code.
I use Django 1.11.4, Python 3.6.2, and a clean app created with ./manage.py startapp testing. The code in models.py:
from django.db import models
from django.db.models import signals
_currency_field_name = lambda name: '{}_extension'.format(name)
class PriceField(models.DecimalField):
def contribute_to_class(self, cls, name):
# add the extra currency field (CharField) to the class
if not cls._meta.abstract:
currency_field = models.CharField(
max_length=3,
editable=False,
null=True,
blank=True
)
cls.add_to_class(_currency_field_name(name), currency_field)
# add the original price field (DecimalField) to the class
super().contribute_to_class(cls, name)
# TODO: set the descriptor
# setattr(cls, self.name, FooDescriptor(self))
class FooModel(models.Model):
price = PriceField('agrhhhhh', decimal_places=3, max_digits=10, blank=True, null=True)
The problems come if I try to create migrations for that models. If executing python manage.py makemigrations following message is shown:
Migrations for 'testing':
testing/migrations/0001_initial.py
- Create model FooModel
Migration file 0001_initial.py has the following content:
# Generated by Django 1.11.4 on 2017-09-11 18:02
from __future__ import unicode_literals
from django.db import migrations, models
import testing.models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='FooModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('price', testing.models.PriceField(blank=True, decimal_places=3, max_digits=10, null=True, verbose_name='agrhhhhh')),
('price_extension', models.CharField(blank=True, editable=False, max_length=3, null=True)),
],
),
]
For me this looks OK so far. But if I then execute ./manage.py migrate testing, django shouts:
Operations to perform:
Apply all migrations: testing
Running migrations:
Applying testing.0001_initial...Traceback (most recent call last):
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/backends/utils.py", line 63, in execute
return self.cursor.execute(sql)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 326, in execute
return Database.Cursor.execute(self, query)
sqlite3.OperationalError: duplicate column name: price_extension
Why does it error out on a duplicate column name: price_extension, when there is only one such field defined in the migrations file? Where does this duplicate field come from and is there a fix for this situation? Thanks!
Edit 1
This exception not only happens with an already existing database but also when I start with an empty database from scratch (deleting SQLite file). After the migrate command failed this is the structure of the DB:
./manage.py dbshell
sqlite> .tables
django_migrations
sqlite> .schema
CREATE TABLE "django_migrations" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "app" varchar(255) NOT NULL, "name" varchar(255) NOT NULL, "applied" datetime NOT NULL);
sqlite> select * from django_migrations;
sqlite>
And full stacktrace:
./manage.py migrate testing
Operations to perform:
Apply all migrations: testing
Running migrations:
Applying testing.0001_initial...Traceback (most recent call last):
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/backends/utils.py", line 63, in execute
return self.cursor.execute(sql)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 326, in execute
return Database.Cursor.execute(self, query)
sqlite3.OperationalError: duplicate column name: price_extension
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "./manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
utility.execute()
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/core/management/__init__.py", line 355, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/core/management/base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/core/management/base.py", line 330, in execute
output = self.handle(*args, **options)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/core/management/commands/migrate.py", line 204, in handle
fake_initial=fake_initial,
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/migrations/executor.py", line 115, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/migrations/executor.py", line 145, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/migrations/executor.py", line 244, in apply_migration
state = migration.apply(state, schema_editor)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/migrations/migration.py", line 129, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/migrations/operations/models.py", line 97, in database_forwards
schema_editor.create_model(model)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/backends/base/schema.py", line 303, in create_model
self.execute(sql, params or None)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/backends/base/schema.py", line 120, in execute
cursor.execute(sql, params)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/backends/utils.py", line 80, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/cachalot/monkey_patch.py", line 113, in inner
out = original(cursor, sql, *args, **kwargs)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/backends/utils.py", line 63, in execute
return self.cursor.execute(sql)
File "/usr/local/var/pyenv/versions/stockmanagement-3.6.2/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 326, in execute
return Database.Cursor.execute(self, query)
django.db.utils.OperationalError: duplicate column name: price_extension
Edit 2
A git repository with the above code can be found under: https://github.com/hetsch/django_testing. This error happens also if one clones this repository (clean project without any DB), calls makemigrations and then migrate.
According to Django ticket #22555 https://code.djangoproject.com/ticket/22555, this method of adding fields is not officially supported. Nonetheless, I made it work with the following simple fix:
def contribute_to_class(self, cls, name):
# add the extra currency field (CharField) to the class
# and prevent adding another field instance if the
# field was allready attached.
if not cls._meta.abstract and not hasattr(cls, _currency_field_name(name)):
currency_field = models.CharField(
max_length=3,
editable=False,
null=True,
blank=True
)
cls.add_to_class(_currency_field_name(name), currency_field)

"relation "social_auth_code" does not exist" when applying migrations on django

I recently switched from django-social-auth to python-social-auth, but it has clearly damage my migrations system. any time I try to migrate changes I got this one :
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 377, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **options.__dict__)
File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/base.py", line 338, in execute
output = self.handle(*args, **options)
File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 161, in handle
executor.migrate(targets, plan, fake=options.get("fake", False))
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/migrations/executor.py", line 68, in migrate
self.apply_migration(migration, fake=fake)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/migrations/executor.py", line 102, in apply_migration
migration.apply(project_state, schema_editor)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/migrations/migration.py", line 108, in apply
operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/migrations/operations/fields.py", line 139, in database_forwards
schema_editor.alter_field(from_model, from_field, to_field)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/schema.py", line 457, in alter_field
self._alter_field(model, old_field, new_field, old_type, new_type, old_db_params, new_db_params, strict)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/schema.py", line 603, in _alter_field
params,
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/schema.py", line 103, in execute
cursor.execute(sql, params)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "social_auth_code" does not exist
The problem being that it only happens in the production version of my app and that for some other reasons, I had to delete my migrations file in the past. Doesn't make it easy to investigate. Anyway, it perfectly work now with my development app but I can't figure out what can be the problem in production, I tried all the "faking migrations" tricks in the world and nothing seems to work.
the only place in the web were I can find such an error is there
but I never used South, so the first answer is not working for me.
Directly digging into the migrations table and sending raw SQL instructions could be the solution but since it is in my production version, I don't feel confortable with tinkering the db ( I got thousands of registered users, there data and all..). In short, I'm in deep sh*t :). Also, I don't know which command to use to directly access the migration table in the db...
Any solution that keeps my data safe is more than welcome :))
When migrating to python_social_auth I got the same error.
This is useful for Django 1.8.
Maybe my solution will help you:
Fake migrate initial of python_social_auth
python manage.py migrate default 0001 --fake
Create yourself migration for initial psa and put it to /your_project/your_app/migrations/0009_migrate_to_psa.py:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import social.apps.django_app.default.fields
from django.conf import settings
import social.storage.django_orm
from social.utils import setting_name
user_model = getattr(settings, setting_name('USER_MODEL'), None) or \
getattr(settings, 'AUTH_USER_MODEL', None) or \
'auth.User'
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(user_model),
('your_app', '0008_last_migration_in_your_app'),
('default', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Code',
fields=[
('id', models.AutoField(
verbose_name='ID', serialize=False, auto_created=True,
primary_key=True)),
('email', models.EmailField(max_length=75)),
('code', models.CharField(max_length=32, db_index=True)),
('verified', models.BooleanField(default=False)),
],
options={
'db_table': 'social_auth_code',
},
bases=(models.Model, social.storage.django_orm.DjangoCodeMixin),
),
migrations.AlterUniqueTogether(
name='code',
unique_together=set([('email', 'code')]),
),
]
Notice the dependencies:
dependencies = [
migrations.swappable_dependency(user_model),
('your_app', '0008_last_migration_in_your_app'),
('default', '0001_initial'),
]
Migrate your project
python manage.py migrate your_app
And migrate all
python manage.py migrate
UPDATE:
Unfortunately, this method requires a model Code in the file models.py your application. Otherwise the table will be deleted from the database when the next operation makemigrations.
/your_project/your_app/models.py:
from social.storage.django_orm import DjangoCodeMixin
class Code(models.Model, DjangoCodeMixin):
email = models.EmailField(max_length=254)
code = models.CharField(max_length=32, db_index=True)
verified = models.BooleanField(default=False)
class Meta:
db_table = 'social_auth_code'
unique_together = ('email', 'code')
I tried to run the solution before and had a bit of difficulties with the dependency.
I ended up just prepending1 the following lines to the Migration.operations list in migration 0007_code_timestamp (exactly as the original first answer suggested)
migrations.CreateModel(
name='Code',
fields=[
('id', models.AutoField(
verbose_name='ID', serialize=False, auto_created=True,
primary_key=True)),
('email', models.EmailField(max_length=75)),
('code', models.CharField(max_length=32, db_index=True)),
('verified', models.BooleanField(default=False)),
],
options={
'db_table': 'social_auth_code',
},
bases=(models.Model, social_django.storage.DjangoCodeMixin),
),
migrations.AlterUniqueTogether(
name='code',
unique_together=set([('email', 'code')]),
),
And make sure to import social_django at the top.
That solved it for me, it was easier than creating a new migration and dealing with the dependency clarification.

Categories

Resources