set first_name and second_name in python shell - django - python

I changed the register logic where now new users have to give their first and second names also. But old users in db don't have those fields filled up, they are empty.
I am wondering now how to set them manually with python manage.py shell, I am using sqlite3, so there is no UI for the db.
is there any solution for it?
the one which came to my mind is to write a update-page for users where they can update their personal info. but then I would need to tell every one of them to do this.

Firstly, I don't know what you mean by "there is no UI for the db" - sqlite has a shell just like any other database, you can go in and write direct SQL update statements.
Secondly, setting fields in the Django shell is just the same as in a view: you import your models, query the instances you want, update the fields, and save the model.
from myapp.models import MyModel
my_instance = MyModel.objects.get(id=whatever)
my_instance.first_name = 'foo'
my_instance.last_name = 'bar'
my_instance.save()

If you are using south, you can do a data migration which is like a schema migration, but deals with data.
You would create a migration, and then add the appropriate code to the forwards method. This way when this migration is applied, data is added for those users that do not have a first and last name.
The other option you have is to do this manually, from the django shell:
>>> from django.contrib.auth import get_user_model
>>> model = get_user_model()
>>> no_names = model.objects.filter(first_name='', last_name='')
>>> no_names.update(first_name='First Name', last_name='Last Name')

Related

How can i set a default value to an OneToOneField relationship which it's automatically generated?

I have two model classes they like below:
from django.db import models
from django.urls import reverse
class Place(models.Model):
address = models.CharField(max_length=80)
class Author(Place):
name = models.CharField(max_length=50)
But when i want to execute makemigartions django shows me error below:
You are trying to add a non-nullable field 'place_ptr' to author without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option:
I have some data in Author table but i dont want to remove that data.
is there anyone could help me please ?
You can delete the old migrations file or entire migration folder for the specific app and then do the python manage.py makemigrations <app_name>
If this is not the solution you wanted then you can find the solution here.

How to reduce max_length of CharField in Django when data already exists in db

I have a CharField on a Django (1.9) model:
alias = models.CharField(max_length=50)
The app is being used and already has data, and there are objects using all 50 characters already. What is the simplest method to reduce the max_length of this field without getting complaints from my production database when I try to migrate? DB is postgresql if it makes a difference.
I think the right way would be simply go the development python terminal and access all the objects of that particular model and truncate the values for alias as:
for object in MyModel.objects.all():
object.alias = object.alias[:REDUCED_LENGTH]
object.save()
and, the change the max_length in the CharField in your model and run migrations.
to reduce max_length=50 to other max_length=20
> python manage.py makemigrations
> python manage.py migrate
all new data that you save will work with new max_length
for exists data you can make simple script
from myproject.models import Mymodel
for obj in Mymodel.objects.all():
obj.Firstname = obj.Firstname[0:3]
obj.save()

Why is save not working in Django?

I'm using manage.py shell and run something like this:
d=Document.objects.get(pk=1)
d.scores
{1:0,2:0,3:0}
d.scores[1]=5
d.scores
{1:5,2:0,3:0}
d.save()
But viewing d in the database reveals that it hasn't been updated. What am I doing wrong?? I checked out what's here, but d is definitely a Document instance.
If it helps, models.py looks like this:
from django.db import models
class Document(models.Model):
fileName=models.CharField(max_length=200)
fileUrl=models.CharField(max_length=200)
scores={1:0,2:0,3:0}
Your 'scores' class variable isn't an instance of any of Django's *Field classes. I would imagine the 'scores' field isn't even on the table in the DB, since the field classes are what defines all of that, and what gets saved to the DB, among other things.

Django model inheritance: create sub-instance of existing instance (downcast)?

I'm trying to integrate a 3rd party Django app that made the unfortunate decision to inherit from django.contrib.auth.models.User, which is a big no-no for pluggable apps. Quoting Malcolm Tredinnick:
More importantly, though, just as in Python you cannot "downcast" with
Django's model inheritance. That is, if you've already created the User
instance, you cannot, without poking about under the covers, make that
instance correspond to a subclass instance that you haven't created yet.
Well, I'm in the situation where I need to integrate this 3rd party app with my existing user instances. So, if hypothetically I am indeed willing to poke about under the covers, what are my options? I know that this doesn't work:
extended_user = ExtendedUser(user_ptr_id=auth_user.pk)
extended_user.save()
There's no exception, but it breaks all kinds of stuff, starting with overwriting all the columns from django.contrib.auth.models.User with empty strings...
This should work:
extended_user = ExtendedUser(user_ptr_id=auth_user.pk)
extended_user.__dict__.update(auth_user.__dict__)
extended_user.save()
Here you're basically just copying over the values from the auth_user version into the extended_user one, and re-saving it. Not very elegant, but it works.
I found this answer by asking on django-user mailing list:
https://groups.google.com/d/msg/django-users/02t83cuEbeg/JnPkriW-omQJ
This isn't part of the public API but you could rely on how Django loads fixture internally.
parent = Restaurant.objects.get(name__iexact="Bob's Place").parent
bar = Bar(parent=parent, happy_hour=True)
bar.save_base(raw=True)
Keep in mind that this could break with any new version of Django.
If you don't like __dict__.update solution you can do this:
for field in parent_obj._meta.fields
setattr(child_obj, field.attname, getattr(parent_obj, field.attname))
I am using Django 1.6, and my ExtendedUser model is from OSQA (forum.models.user.User). For some bizarre reason the above solutions with dict.__update__ and with setattr sometimes fail. This may have to do with some other models that I have, that are putting constrains on the user tables. Here are two more workarounds that you can try:
Workaround #1:
extended_user = ExtendedUser(user_ptr_id = user.pk)
extended_user.save() # save first time
extended_user.__dict__.update(user.__dict__)
extended_user.save() # save second time
Workaround #2:
extended_user = ExtendedUser(user_ptr_id = user.pk)
extended_user.__dict__.update(user.__dict__)
extended_user.id=None
extended_user.save()
That is, sometimes saving the new child instance fails if you set both pk and id, but you can set just pk, save it, and then everything seems to work fine.
There is an open bug for this very question:
https://code.djangoproject.com/ticket/7623
The proposed patch (https://github.com/django/django/compare/master...ar45:child_object_from_parent_model) is not using obj.__dict__
but creates an dictionary with all field values cycling over all fields.
Here a simplified function:
def create_child_from_parent_model(child_cls, parent_obj, init_values: dict):
attrs = {}
for field in parent_obj._meta._get_fields(reverse=False, include_parents=True):
if field.attname not in attrs:
attrs[field.attname] = getattr(parent_obj, field.attname)
attrs[child_cls._meta.parents[parent_obj.__class__].name] = parent_obj
attrs.update(init_values)
print(attrs)
return child_cls(**attrs)
create_child_from_parent_model(ExtendedUser, auth_user, {})
This method has the advantage that methods that are overwritten by the child are not replaced by the original parent methods.
For me using the original answers obj.__dict__.update() led to exceptions as I was using the FieldTracker from model_utils in the parent class.
What about something like this:
from django.forms.models import model_to_dict
auth_user_dict = model_to_dict(auth_user)
extended_user = ExtendedUser.objects.create(user_ptr=auth_user, **auth_user_dict)
#guetti's answer worked for me with little update => The key was parent_ptr
parent_object = parent_model.objects.get(pk=parent_id)
new_child_object_with_existing_parent = Child(parent_ptr=parent, child_filed1='Nothing')
new_child_object_with_existing_parent.save()
I wanted to create entry in my profile model for existing user, my model was like
from django.contrib.auth.models import User as user_model
class Profile(user_model):
bio = models.CharField(maxlength=1000)
another_filed = models.CharField(maxlength=1000, null=True, blank=True)
At some place I needed to create profile if not exists for existing user so I did it like following,
The example that worked for me
from meetings.user import Profile
from django.contrib.auth.models import User as user_model
user_object = user_model.objects.get(pk=3)
profile_object = Profile(user_ptr=user_object, bio='some')
profile_object.save()

Django admin site not displaying ManyToManyField relationship

I'm working on what I think is a pretty standard django site, but am having trouble getting my admin section to display the proper fields.
Here's my models.py:
class Tech(models.Model):
name = models.CharField(max_length = 30)
class Project(models.Model):
title = models.CharField(max_length = 50)
techs = models.ManyToManyField(Tech)
In other words, a Project can have different Tech objects and different tech objects can belong to different Projects (Project X was created with Python and Django, Project Y was C# and SQL Server)
However, the admin site doesn't display any UI for the Tech objects. Here's my admin.py:
class TechInline(admin.TabularInline):
model = Tech
extra = 5
class ProjectAdmin(admin.ModelAdmin):
fields = ['title']
inlines = []
list_display = ('title')
admin.site.register(Project, ProjectAdmin)
I've tried adding the TechInline class to the inlines list, but that causes a
<class 'home.projects.models.Tech'> has no ForeignKey to <class 'home.projects.models.Project'>
Error. Also tried adding techs to the fields list, but that gives a
no such table: projects_project_techs
Error. I verified, and there is no projects_project_techs table, but there is a projects_tech one. Did something perhaps get screwed up in my syncdb?
I am using Sqlite as my database if that helps.
I've tried adding the TechInline class to the inlines list, but that causes a
'TechInLine' not defined
Is that a straight copy-paste? It looks like you just made a typo -- try TechInline instead of TechInLine.
If your syncdb didn't create the proper table, you can do it manually. Execute this command:
python manage.py sqlreset <myapp>
And look for the definition for the projects_project_techs table. Copy and paste it into the client for your database.
Assuming your app is called "projects", the default name for your techs table will be projects_tech and the projects table will be projects_project.
The many-to-many table should be something like projects_project_techs
#John Millikin - Thanks for the sqlreset tip, that put me on the right path. The sqlreset generated code that showed me that the projects_project_techs was never actually created. I ended up just deleting my deb.db database and regenerating it. techs then showed up as it should.
And just as a sidenote, I had to do an admin.site.register(Tech) to be able to create new instances of the class from the Project page too.
I'll probably post another question to see if there is a better way to implement model changes (since I'm pretty sure that is what caused my problem) without wiping the database.

Categories