Django1.5 not overwriting auth_users - python

I would like a bigger auth_user table, including 2-3 extra fields.
The thing is that the code below is creating a new one, exactly the same as the auth_user one with the extra fields but it is not replacing it.
settings.py
AUTH_PROFILE_MODULE = "myaccount.MyUser"
models.py
from django.contrib.auth.models import AbstractUser
class MyUser(AbstractUser):
gender = models.DateField()
location = models.CharField(max_length=30)
birthday = models.CharField(max_length=30)
Instead of creating a new table called myaccount_MyUser. How can I replace the current auth_user table instead of creating a new table?

I believe that this one can help you :
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-user

One hackish way that I didn't try and don't recommend would be to specify the table name in the model with:
class MyUser(AbstractUser):
class Meta:
db_table = auth_user
What I recommend is going along with the new table and migrating the data from the old one using south datamigration. Here is a detailed answer on how to do that:
Migrating existing auth.User data to new Django 1.5 custom user model?

I think that you have to
import first django.contrib.auth.models
import AbstractUser
in your models.py before to get a way to extend with AbstractUser. it should work with that

Related

Inheritance model update to its parent model

I need extend a model from another model.
Case:
core/models.py
class Master(models.Model):
code = models.CharField(max_length=30, unique=True)
name = models.CharField(max_length=100, blank=False, null=False)
class Meta:
abstract = True
class City(Master):
zipcode = models.IntegerField()
custom/models.py
from core.models import City
class City(City)
newfield = models.CharField(max_length=20)
custom is an app.
I have tried with proxy model but it is not what I need, since proxy model adds a new table. https://docs.djangoproject.com/en/2.2/topics/db/models/#proxy-models
I need is that when I migrate add the new field to City.
More info.
In core the table is created and in custom you can add new fields that the client needs. The idea is that core is only maintained as standard.
Proxy models don't add new tables. From the docs link you mentioned:
The MyPerson class operates on the same database table as its parent Person class.
If you want one table called core_city, and another called custom_city, the second one having an extra field, you simply subclass it. Perhaps it would be easier to use an alias:
from core.models import City as CoreCity
class City(CoreCity):
newfield = models.CharField(max_length=20)
custom_city will have all fields from core_city, plus a newfield. The description of how this works (and an example) is covered in the docs section Multi-table inheritance.
If what you want is to have one single database table, then you should use a proxy Model, however they really don't allow you to create new fields. The field should be created in the parent model, or otherwise exist in the database and not be handled by Django migrations at all.
You are looking for Abstract base classes models:
Abstract base classes are useful when you want to put some common information into a number of other models. You write your base class and put abstract=True in the Meta class.
This is the base class:
#core/models.py
class City(Master):
zipcode = models.IntegerField()
class Meta:
abstract = True # <--- here the trick
Here your model:
#custom/models.py
from core.models import City as CoreCity
class City(CoreCity):
newfield = models.CharField(max_length=20)
For many uses, this type of model inheritance will be exactly what you want. It provides a way to factor out common information at the Python level, while still only creating one database table per child model at the database level.
You can update or create your class constants after its defined like this
from core.models import City
City.newfield = models.CharField(max_length=20)
You may need to use swappable models, using them you can define a City class and change it with whichever model you need later,
but that way you can't import and use the base City model directly, you may need to provide a method like get_city_model for that, as your public API.
class City(Master):
zipcode = models.IntegerField()
class Meta:
swappable = 'CORE_CITY_MODEL'
and maybe replace it later with some other model, then just set CORE_CITY_MODEL to that model in the form of 'app_name.model_name'.
The django.contrib.auth is a good example of this, you may consider checking User model and get_user_model method. Although I think you may face problems if you change your city model after you did run migrate, it may not move your data to the new table, but I'm not sure about this.

Django Two Model Fields, same DB Column

We are trying to work with legacy DB Tables that were generated outside of Django and are not structured in an ideal way. We also can not modify the existing tables.
The DB uses the same user ID (pk) across all the tables, wether or not there is a record for that user ID. It also uses that ID as a PK on the other tables, rather than rely on them to auto increment their own IDs.
So imagine something like this below:
class Items(models.Model):
user_id = models.ForeignKey('User', db_column='UserID')
class User(models.Model):
user_id = models.IntegerField(primary_key=True)
class UserTypeA(models.Model):
user_id = models.IntegerField(primary_key=True) # Same Value as User
class UserTypeB(models.Model):
user_id = models.IntegerField(primary_key=True) # Same Value as User
What we thought of creating a relationship between Items and UserTypeA (as well as UserTypeB) is to create another field entry that uses the same column as the user_id.
class Items(models.Model):
user_id = models.ForeignKey('User', db_column='UserID')
user_type_a = models.ForeignKey('UserTypeA', db_column='UserID')
user_type_b = models.ForeignKey('UserTypeB', db_column='UserID')
This unfortunately returns a "db_column is already used" type error.
Any thoughts on how to better approach the way what we're trying to do?
A detail to note is that we're only ever reading from this databases (no updates to), so a read-only solution is fine.
Thanks,
-RB
I've solved a similar problem with this (this code should be put before the definition of your Model):
from django.db.models.signals import class_prepared
def remove_field(sender, **kwargs):
if sender.__name__ == "MyModel":
sender._meta.local_fields.remove(sender.myFKField.field)
class_prepared.connect(remove_field)
(Tested in Django 1.5.11)
Django uses local_fields to make the CREATE TABLE query.
So, I've just attached the signal class_prepared and check if sender equals the class I was expecting. If so, I've removed the field from that list.
After doing that, the CREATE TABLE query didn't include the field with same db_column and the error did not ocurr.
However the Model still working properly (with manager methods properly populating the removed field from local_fields), I can't tell the real impact of that.

Add text to a cell without overwriting existing data

I am currently working with one Django project.
I have the dictionary in it:
from models.py
class teltab(models.Model):
code=models.CharField(max_length=255)
telescope=models.CharField(max_length=255)
comment=models.CharField(max_length=255,blank=True)
and a form to add data to the dictionary:
class newtelescopesform(forms.ModelForm):
class Meta:
model=teltab
Usually I get a comment from the form and writes it to the dictionary:
from views.py
if len(request.GET['comment'])>0:
commentq=request.GET['comment']
tel_list.update(comment=commentq)
for item in tel_list:
item.save()
But now I need to append a new comment to an already existing cell in the resulting table.
Namely my table looks like this
and I want to get this
In fact either you define new comment model with a ForeignKey: teltab
class telTabModel(models.Model):
code=models.CharField(max_length=255)
telescope=models.CharField(max_length=255)
class CommentModel(models.Model):
teltab = models.ForeignKey('telTabModel', related_name='comments')
# ...
Or if you are using PostgreSQL you can use ArrayField as explained:
from django.contrib.postgres.fields import ArrayField
class telTabModel(models.Model):
code=models.CharField(max_length=255)
telescope=models.CharField(max_length=255)
comments = ArrayField(models.CharField(max_length=200), blank=True),
If you are not using PosgreSQL and you still want to use array you I will recommend Jsonfield
pip install jsonfield
from jsonfield import JSONField
class telTabModel(models.Model):
code=models.CharField(max_length=255)
telescope=models.CharField(max_length=255)
comments = JSONField(default=[])
I suppose u should change your model comment field type to TextField:
comment=models.TextField(blank=True)
Then just add "/n{new line}" to it
Edit: Dan's right, it s not a good idea there's opportunity to store lists in model if i'm not mistaken.

Proper way to log Django User activity

What's the proper way to log user activity in Django?
For example let's say a user has Groups, and I'd like to keep a record of when Object1 has been added or removed.
The method that comes to mind is to create a new record every time and pull the latest record but this feels wrong (and causes some filtering problems, eg: you can't just filter on is_member=True since you'll get stale results). Is there a proper way to log these in Django?
You can use django-auditable-models for that. It will hook in the django workflow, and will avoid that you have to write all logic yourself.
You can use loggers in Django.
https://docs.djangoproject.com/en/1.8/topics/logging/#topic-logging-parts-loggers
To log something like that I recommend you to create an core app with a TimeStampModel model:
from django.db import models
from django.utils.timezone import now
class TimeStampModel(models.Model):
"""
TimeStampModel class allows us to follow creation and update of each inherit instance
"""
created_at = models.DateTimeField(auto_now_add=now(), editable=False)
updated_at = models.DateTimeField(auto_now=now(), editable=False)
class Meta:
abstract = True
Now, inherit each models from TimeStampModel that you want to record creation or update date.
E.g:
from django.db import models
from core.models import TimeStampModel
class Token(TimeStampModel):
uuid = models.CharField(max_length=255, primary_key=True)
# ...
You can also add a delete attribute (Boolean) to realize logical delete. And the last update, will be the date of deletion.
Two Scoops of Django 1.8 recommends also this practice.

User-defined text fields in django admin

Django (and database) newbie here.
I'm trying to figure out a way to enable the creation of n custom text fields for a table (let's call it Book) using the admin interface. I would like a way for the user to define new text fields through the admin interface (instead of defining fields like CustomField1, CustomField2, etc, through a model followed by running manage.py syncdb).
Ultimately, I would want to create a separate table called CustomFields. The django admin user (who is not a programmer), would go and enter the custom text fields in this table (e.g. pubdate, isbn, country). Then, when doing data entry for a Book, they would hit "+" for every custom field they wanted, have them available in a dropdown, and add accompanying text for the custom field. The text entered for each field is specific to the parent Book.
Any suggestions? I have a feeling there's a simple solution that I'm somehow not grasping here.
Where you might run into problems is because Django will not recreate tables or columns based on changing model declarations. This means you're unable to add fields to a table at run-time without running the generated sql on your database manually. What you'll need, instead, is a way of defining custom fields, and linking them to your model.
What I'd suggest is the following:
class CustomField(models.Model):
name = models.CharField(max_length=32)
class Book(models.Model):
... fields
class CustomValue(models.Model):
field = models.ForeignKey(CustomField)
value = models.CharField(max_length=255)
book = models.ForeignKey(Book)
The validation on the above is fairly non-existant, and this doesn't allow you to define required custom fields for each model, but you should be able to come up with that part if you need it later on.
# taken and modified from django online tutorial
class CustomValueInline(admin.StackedInline):
model = CustomValue
extra = 3
class BookAdmin(admin.ModelAdmin):
fieldsets = [
# your fields in here
]
inlines = [CustomValueInline]
admin.site.register(Book, BookAdmin)
This will allow users to select up to 3 custom fields and values directly, with the option to add more if they wish.
Edit: Changed the answer to reflect further information in comments.
For the beginning you can create one model for the book and one for the text field, both connected through a foreign key relation. You can easily administrate this then through django's inline admins, which will enable you to add more text fields!
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
class TextField(models.Model):
text = models.TextField
book = models.ForeignKey(Book)
# admin.py
from django.contrib import admin
from models import TextField, Book
class TextAdmin(admin.TabularInline):
model = TextField
class BookAdmin(admin.ModelAdmin):
inlines = [TextAdmin]
admin.site.register(Book, BookAdmin)

Categories

Resources