Use django-reviews package with an app which uses customized user model - django

I am working on a django App where I am using a custom user models for AUTH_USER_MODEL i.e AUTH_USER_MODEL = 'account.User'I extended the AbstractBaseUser class to create my model that is like
class User(AbstractBaseUser):
is_provider = models.BooleanField(_('Provider status'), default=False)
USERNAME_FIELD = 'email'
..........
In my settings.py file i added AUTH_USER_MODEL = 'account.User' means now my User model is accounts.User not django.contrib.auth.User.
I want to add django-reviews app app im my webapp to get the reviews but the problem is django-reviews used DJango.contrib.auth.User as its default AUTH_USER_MODEL.
class Review(models.Model):
"""A ``Review`` consists on a comment and a rating.
"""
content_type = models.ForeignKey(ContentType, verbose_name=_(u"Content type"), related_name="content_type_set_for_%(class)s")
content_id = models.PositiveIntegerField(_(u"Content ID"), blank=True, null=True)
content = generic.GenericForeignKey(ct_field="content_type", fk_field="content_id")
# if the user is authenticated we save the user otherwise the name and the
# email.
user = models.ForeignKey(User, verbose_name=_(u"User"), blank=True, null=True, related_name="%(class)s_comments")
session_id = models.CharField(_(u"Session ID"), blank=True, max_length=50)
user_name = models.CharField(_(u"Name"), max_length=50, blank=True)
user_email = models.EmailField(_(u"E-mail"), blank=True)
comment = models.TextField(_(u"Comment"), blank=True)
score = models.FloatField(_(u"Score"), choices=SCORE_CHOICES, default=3.0)
active = models.BooleanField(_(u"Active"), default=False)
creation_date = models.DateTimeField(_(u"Creation date"), auto_now_add=True)
ip_address = models.IPAddressField(_(u"IP address"), blank=True, null=True)
now it is giving me error
File "/home/user/dir/env/local/lib/python2.7/site-packages/django/core/management/base.py", line 314, in validate
raise CommandError("One or more models did not validate:\n%s" % error_text)
django.core.management.base.CommandError: One or more models did not validate:
reviews.review: 'user' defines a relation with the model 'auth.User', which has been swapped out. Update the relation to point at settings.AUTH_USER_MODEL.
Tell me a way that how can i use the django-reviews with my app while not using the default auth model as my AUTH_USER_MODEL.

Related

Recording user activity in django?

I have a project in which some user can perform CRUD activities. I want to record who did what and when. Currently, I am thinking of making a model
class UserAction(models.Model):
user_id = models.CharField(max_length=100)
action_flag = models.CharField(max_length=100)
class_id = models.CharField(max_length=100)
action_taken_at = models.DateTimeField(default=datetime.now())
and making a function that fills my UserAction table. Is there any better way to do this?
app/models.py:
from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
class Action(models.Model):
sender = models.ForeignKey(User,related_name='user',on_delete=models.CASCADE)
verb = models.CharField(max_length=255)
target_ct = models.ForeignKey(ContentType, blank=True, null=True,
related_name='target_obj', on_delete=models.CASCADE)
target_id = models.PositiveIntegerField(null=True, blank=True)
target = GenericForeignKey('target_ct', 'target_id')
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-created',)
def __str__(self):
return self.pk
app/admin.py
from .models import Action
admin.site.register(Action)
How you can use it ?
you can now import this models(Action) inside any of yours views.py.
Example if you have a post and a user likes it.you can just write
Action.objects.create(sender=request.user,verb="likes this post",target=post)
and now when you look at your admin you will see that tartget_id=post.pk
Here I assume that a user is authenticated and you can change it for your own.Happy coding!!!
You can do it by creating a model in
Models.py
class Auditable(models.Model):
ip = models.GenericIPAddressField(null=True)
user_agent = models.CharField(max_length=255, blank=True)
remote_host = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="%(app_label)s_%(class)s_created_by", null=True, blank=True) # this is for web user
modified_at = models.DateTimeField(auto_now=True, blank=True, null=True)
modified_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="%(app_label)s_%(class)s_modified_by", null=True, blank=True) # this is for web user
class Meta:
abstract = True
def get_fields(self):
list_fields = ['ip', 'user_agent',
'remote_host', 'created_by', 'modified_by']
return [(field.verbose_name, field._get_val_from_obj(self)) for field in self.__class__._meta.fields if field.name not in list_fields and not
(field.get_internal_type() == "DateTimeField" and
(field.auto_now is True or field.auto_now_add is True)) and
field.concrete and (not field.is_relation or field.one_to_one or
(field.many_to_one and field.related_model))]
You can give any class name (i have given auditable). So all you have to do is pass this class (auditable) in your every model instead of models.Model
For Eg:
class Student(Auditable):
By doing this it will add all the auditable fields records in every table you have created.
Hope you may get your answer by doing this.

Get All Changes of Any registered model of a single user django-simple-history

# settings.py
INSTALLED_APPS = [
# ...
'simple_history',
# ...
]
MIDDLEWARE = [
# ...
'simple_history.middleware.HistoryRequestMiddleware',
# ...
]
Models:
from django.db import models
from apps.companies.models import Company
from simple_history.models import HistoricalRecords
# Create your models here.
class User(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=20)
history = HistoricalRecords()
class Contact(TimeStamp):
name = models.CharField(max_length=100, verbose_name='Person Name')
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
phone_number = models.CharField(max_length=100, verbose_name='Personal Number', null=True, blank=True)
email = models.EmailField(null=True, blank=True, verbose_name='Personal Email')
designation = models.CharField(max_length=100)
history = HistoricalRecords()
def __str__(self):
return self.name
user = User.objects.first()
is there anyway to get all changes any model by the user
Your question seems similar than this issue on the django-simple-history repository : https://github.com/jazzband/django-simple-history/issues/684
You'd have to query each historical model since they're all in
separate tables. You could build a way to automatically detect which
models are historical and get them though.

how to use custom user model for django-graphql-auth

I am using graphql in my project and want to generate token while registration. Even though django-graphql-auth has all the written mutation, it uses a different user model. But I want to use my custom user model. What should I do?
This is my user model
class CustomUser(AbstractUser):
"""
Customized User Model
"""
email = models.EmailField(blank=True, null=True,
max_length=256, unique=True)
mobile_no = models.CharField(
max_length=20, blank=True, null=True, unique=True)
verification_code = models.CharField(max_length=6)
code_valid_till = models.DateTimeField(blank=True, null=True)
timezone = models.CharField(max_length=40, blank=True, null=True)
country = models.CharField(max_length=20, default='BD', choices=COUNTRIES)
pin_verified = models.BooleanField(default=False)
email_verified = models.BooleanField(default=False)
modified_on = models.DateTimeField('date modified', auto_now=True)
created_on = models.DateTimeField(auto_now_add=True)
# For password reset
reset_verification_code = models.CharField(
max_length=6, blank=True, null=True)
reset_code_valid_till = models.DateTimeField(blank=True, null=True)
reset_request = models.BooleanField(default=False)
reset_valid_till = models.DateTimeField(blank=True, null=True)
class Meta:
verbose_name_plural = "User"
def __str__(self):
if not self.is_anonymous:
return "{} - {}".format(self.mobile_no, self.email)
else:
return "Anon"
#property
def get_full_name(self):
return super().get_full_name()
def get_all_permissions(self, obj=None):
return super().get_all_permissions(obj=obj)
def send_email(self, subject, message, to_email: list, from_email=None, **kwargs):
send_mail_to_user(subject, message, from_email, to_email, **kwargs)
I'm the author of the package. Now the documentation site has a custom user model in the quickstart, you can see it here. Currently, it's not documented how to use it with a custom user model, but it is already an open issue, you can see it here. I will paste the same answer that is on the Github.
From Django docs:
Changing to a custom user model mid-project
Changing AUTH_USER_MODEL after you’ve created database tables is
significantly more difficult since it affects foreign keys and
many-to-many relationships, for example.
So, make sure to create the custom user model when you start your project.
Add the following to your custom user model
Following the Django custom user model.
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
# ...
USERNAME_FIELD = "<username_filed_name>" # e.g: "username", "email"
EMAIL_FIELD = "<email_field_name>" # e.g: "email", "primary_email"
Add your custom user model in the settings
See here for more info.
# settings.py
AUTH_USER_MODEL = 'myapp.CustomUser'
Please let me know if you have further questions :)
Edit: Add the mobile_no in the registration
Use the REGISTER_MUTATION_FIELDS or REGISTER_MUTATION_FIELDS_OPTIONAL.
# settings.py
GRAPHQL_AUTH = {
# ...
REGISTER_MUTATION_FIELDS = [
# ...
'mobile_no'
]
# or
REGISTER_MUTATION_FIELDS_OPTIONAL = ['mobile_no']
# You can set the graphene base scalars:
REGISTER_MUTATION_FIELDS = {
"email": "String",
"username": "String",
"mobile_no": "String",
}
}

How to keep fields in user model in Django and add some extra field

I want to add some extra fields to my user model and I read custom user model with inherit from abstractuser class but when I implement user model Django username field and etc was gone.
A solution is use another model like profile but I want add extra fields to Django user model. Is this possible?
You can use a custom User model:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
"""
Custom User Model
"""
TIMEZONES = tuple(zip(pytz.all_timezones, pytz.all_timezones))
username = models.CharField(max_length=255, unique=True)
full_name = models.CharField(max_length=255, blank=True, null=True)
email = models.CharField(max_length=255, unique=True)
image = models.ImageField(upload_to=get_image_path, blank=True, null=True)
timezone = models.CharField(max_length=32, choices=TIMEZONES, default="UTC")
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]
def __str__(self):
return self.email
You will have to register your custom model in the settings.py file:
# Registering the Custom User Model
AUTH_USER_MODEL = 'my_app.User'

Django Server Killed

I am running Django 1.6 with a custom user model. The user model inherits AbstractBaseUser, PermissionsMixin and works fine. It let's me call login() and authenticate() and when I do syncdb it creates it with no errors and will allow me to create a superuser in the command line interface.
I am trying to use the Django admin panel. I can access /admin/ fine and login and it will display the list of registered models.
I can modify all models, with the exception of "user". I can click the "user" model and see a list of users, however if I try and add a new user or edit an existing user, the request will take approximately 1 minute and then the django web server will exit with the message "Killed".
I would post some code however I have no idea what would be relevant because the error is so vague.
Is there another error log somewhere I can find out more details?
Edit:
Custom user model code:
class User(AbstractBaseUser, PermissionsMixin):
id = models.AutoField(primary_key=True)
full_name = models.CharField("Full Name", max_length=100)
email_address = models.CharField(max_length=255, unique=True, db_index=True)
company_name = models.CharField(max_length=50, blank=True, null=True)
time_zone = models.CharField(max_length=50, blank=True, null=True)
activation_key = models.CharField(unique=True, max_length=50, blank=True, null=True)
location = models.ForeignKey(Location, related_name='fk_user_2_country', blank=True, null=True)
username = models.CharField(max_length=20, blank=True, null=True, unique=True)
is_staff = models.BooleanField(default=False)
class Meta:
db_table = 'user'
USERNAME_FIELD = 'email_address'
objects = UserManager()
REQUIRED_FIELDS = ['full_name',]
def get_full_name(self):
return self.email_address
def get_short_name(self):
return self.email_address
def activate_email(self, activation_key):
if self.activation_key == activation_key:
self.activation_key = None
self.save()
return True
else:
return False
def __unique__(self):
return self.email_address
def is_active(self):
return self.activation_key is None
This was caused by the relationship to the "Location" table location = models.ForeignKey(Location, related_name='fk_user_2_country', blank=True, null=True).
This table contained 3.3 Million rows, the Django admin panel was trying to list them all and as a result was crashing.