I'm working on a project on how to create Two users : buyers/Sellers for Web using Django as Backend.
I've started the app "users"
I've read the Django Documentation about CustomUserModel
But Honestly don't know where to start from.
Any Suggestions?
In my opinion, a Buyer might be a seller and a seller might be a Buyer.
There are some suggestions:
Create your own application named users (This will help you full control User object in future).
Set your AUTH_USER_MODEL settings to users.User: AUTH_USER_MODEL = 'users.User' As you defined.
Define model Seller - OneToOne -> User: This contains seller's properties, Just create when access via user.seller
Define model Buyer - OneToOne -> User: This contains buyer's properties, just create when access via user.buyer
class User(AbstractUser):
# Your user's properties
# Your user's method
#property
def buyer(self):
try:
return Buyer.objects.get(user=self)
except Buyer.DoesNotExist:
default_value_of_buyer = {}
# Or define default value at model fields
return Buyer.objects.create(user=self, **default_value_of_buyer)
#property
def seller(self):
try:
return Seller.objects.get(user=self)
except Seller.DoesNotExist:
default_value_of_seller = {}
# Or define default value at model fields
return Seller.objects.create(user=self, **default_value_of_seller)
class Buyer(models.Model):
"""
You can add this to admin page to make some actions with Buyer
"""
user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True, on_delete=models.CASCADE, related_name='buyer_profile')
# Other properties of Buyer
def __str__(self):
return "%s's Buyer profile" % self.user
class Seller(models.Model):
"""
You can add this to admin page to make some actions with Seller
"""
user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True, on_delete=models.CASCADE, related_name='seller_profile')
# Other properties of Seller
def __str__(self):
return "%s's Seller profile" % self.user
It is not that hard buddy look:
you create a model User
class User(models.Model):
.........
types = (('b','buyer'),('s','seller'))
user_type = models.CharField(max_length=7, choices=types)
so every field has this argument called choices, it is a tuple that has tuples in it, every sub tuple is a choice and every choice has two elements the first one is what appears in the back end and the second element is what appears in the user interface, so 'b' is what appears in the back end and 'buyer' is what the user see in the form in the web site. Tell if that didn't work for you
class Account(models.Model):
types = (
('B', 'BUYER' ),('S', 'SELLER')
)
name = models.Charfield(max_length=15)
username = models.CharField(max_length=15)
email = models.EmailField()
password = models.CharField(max_length=16)
user_type = models.CharField(max_length=12, choices=types)
TRY THIS AND THEN GO TO YOUR ADMIN PAGE AND YOU WILL UNDERSTAND EVERYTHING
Related
Like :
class Article (models.Model):
user = models.ForeignKey('User', related_name="articles")
def __init___(self):
self.user = 'Friendy'
Presuming you mean to add a default value to the user field, there are two ways: either a simple value based default, or you can use a callable as the default. The documentation for this can be found at https://docs.djangoproject.com/en/2.2/ref/models/fields/#default
If you want to default to specific user, then you would need to know the id of the user, like so:
class Article (models.Model):
user = models.ForeignKey(
'User',
related_name="articles",
default=1,
help_text="There better be a user with an id of 1 or this will not work",
)
def __init___(self):
self.user = 'Friendy'
The other way is to define a callable that returns the id of the user, like so:
def get_first_user():
user = User.objects.first()
if user:
return user.pk
return None
class Article (models.Model):
user = models.ForeignKey(
'User',
related_name="articles",
default=get_first_user,
help_text="There better be a user with an id of 1 or this will not work",
)
def __init___(self):
self.user = 'Friendy'
The reason we return the id and not the User instance is because of this line in the docs:
For fields like ForeignKey that map to model instances, defaults should be the value of the field they reference (pk unless to_field is set) instead of model instances.
I want to design a model for the currrent user to see all the people he referred. I create another model to keep track of all the referral relation between users, such as 'stephen -> jack', 'stephen -> mike'
class CustomUser(AbstractBaseUser):
// ....... a lot more fields
referred_who = models.ForeignKey('referral', blank=True, null=True, on_delete = models.CASCADE)
class Referral(models.Model):
referrer = models.ForeignKey(CustomUser, on_delete = models.CASCADE)
referred = models.ForeignKey(CustomUser, on_delete = models.CASCADE, related_name='referred')
class Meta:
unique_together = (("referrer", "referred"),)
def __str__(self):
return self.referrer.username + ' -> ' + self.referred.username
The question I am having right now is that one user can refer multiple users, but the field 'referred_who' I use to keep track of all the referral relations can only keep one of them. In my back-end admin it shows:
Referred who: stephen1 -> stephen2 (with a dropdown with all the relations but I can only choose one of them)
What I want is somethig like:
Referred who: stephen1 -> stephen2 stephen1 -> stephen3 stephen1 -> stephen4
And I can access this 'Referred_who' field to get all the relations this current user has.
Is there a way to add to the foreign key field instead of just choosing one of them? Can someone show me an example to do it? Many thanks.
You don't need a Referral class. Your referred_who field can "point" to the CustomUser. I renamed it to referred_by and added related_name='referees'. This would mean that if user A referred user B and user B referred user C and D, then B.referred_by == A and B.referees == (C, D):
class CustomUser(AbstractBaseUser):
referred_by = models.ForeignKey('self', blank=True, null=True, on_delete = models.CASCADE, related_name='referees')
Then, you could create a custom form to display in the admin, something like:
from django.contrib import admin
from django import forms
from django.db import models
class CustomUserForm(forms.ModelForm):
class Meta:
model = CustomUser
fields = '__all__'
referees = forms.ModelMultipleChoiceField(queryset=CustomUser.objects.all())
def __init__(self, *args, **kwargs):
super(CustomUserForm, self).__init__(*args, **kwargs)
if self.instance:
self.fields['referees'].initial = self.instance.referees.all()
class CustomUserAdmin(admin.ModelAdmin):
form = CustomUserForm
admin.site.register(CustomUser, CustomUserAdmin)
NOTE: This won't save the chosen users in the referees field yet, you would need to do that by overriding the save method in the form but I do hope this gets you started.
So I have the following models.py
class Incubators(models.Model): # These are our database files for
the Incubator Portal
incubator_name = models.CharField(max_length=30)
owner = models.CharField(max_length=30)
city_location = models.CharField(max_length=30)
description = models.TextField(max_length=2500)
rating = models.FloatField(validators=[MinValueValidator(0), MaxValueValidator(10)])
logo = models.CharField(max_length=30)
picture = models.CharField(max_length=30)
def __str__(self): # Displays the following stuff when a query is made
return self.incubator_name + '-' + self.owner
Now what I am trying to do is create a form for user who has to fill the above field for advertising there incubator on the wall.
Before posting, I want to make sure that these details get verified by the admin (django admin), and after verification from admin it gets posted on the wall ? Is there any model field for the same specially meant for admin ?
You can use
if request.user.is_superuser:
...
else:
raise Http404
I have a customer model in Bcustomer app that extends the django User model, So I will save the basic details such as name in User table and the remaining data (city, etc) in customer table.
When I call the below code through API, it shows the following error. But data is saving in the tables. I also want to implement the get and put calls for this api.
Got AttributeError when attempting to get a value for field `city` on serializer `CustomerSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `User` instance.
Original exception text was: 'User' object has no attribute 'city'.
my Bcustomer/models.py
class BCustomer(models.Model):
customer = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True, blank=True )
address = models.CharField(max_length=50)
city = models.CharField(max_length=256)
state = models.CharField(max_length=50)
user = models.ForeignKey(settings.AUTH_USER_MODEL, db_index=True, on_delete=models.CASCADE, related_name='customer_creator')
# more fields to go
def __str__(self):
# return str(self.name) (This should print first and last name in User model)
class Meta:
app_label = 'bcustomer'
my Bcustomer/serializers.py
from django.contrib.auth import get_user_model
from models import BCustomer
class CustomerSerializer(serializers.HyperlinkedModelSerializer):
city = serializers.CharField()
class Meta:
model = get_user_model()
fields = ('first_name', 'email','city')
def create(self, validated_data):
userModel = get_user_model()
email = validated_data.pop('email', None)
first_name = validated_data.pop('first_name', None)
city = validated_data.pop('city', None)
request = self.context.get('request')
creator = request.user
user = userModel.objects.create(
first_name=first_name,
email=email,
# etc ...
)
customer = BCustomer.objects.create(
customer=user,
city=city,
user=creator
# etc ...
)
return user
my Bcustomer/views.py
class CustomerViewSet(viewsets.ModelViewSet):
customer_photo_thumb = BCustomer.get_thumbnail_url
permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
queryset = BCustomer.objects.all()
serializer_class = CustomerSerializer
my Bcustomer/urls.py
router.register(r'customer', views.CustomerViewSet, 'customers')
POST request format
{
"first_name":"Jsanefvf dss",
"city":"My City",
"email":"myemail#gmail.com",
#more fields
}
I also need to implement put and get for this api. Now data is saving in both tables but shows the error.
Sure it complains.
Validation goes well, so does the creation but once it's created, the view will deserialize the result and return it to the client.
This is the point where it goes south. Serializer is configured to think that city is a field of the default user while it actually is part of BCustomer. In order to work this around, you should set the source argument to the city field. You might need to update the serializer's create/update to reflect that change, not sure about that one.
I'm trying to build a user profile which builds on the default Django user. I'm trying to extend the default user with an extra fields like this:
class MyMember(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL) #not sure about this
birthday = models.DateField()
USERNAME_FIELD = 'user' #how to use username field from default user?
REQUIRED_FIELDS = ['birthday',]
def __unicode__(self):
return self.username
But I'm getting this error: 'Manager' object has no attribute 'get_by_natural_key'? Why?
I would also like the USERNAME_FIELD to be the username from the default user. How?
Here's the UserProfile model class I use to extend the User model in my demo website:
#Private function required by image field.
def _get_upload_file_name_w_sub_dir(instance, filename):
return "uploaded_files/{0}{1}_{2}".format("profile_pic/", (str(time()).replace(".", "_"), filename))
class UserProfile(models.Model):
# This line is required. Links UserProfile to a User model instance.
# related_name is so you can reference *this* model as "user.profile"
# instead of "user.userprofile"
user = models.OneToOneField(User, related_name="profile")
# The additional attributes we wish to include.
year_discovered = models.IntegerField(blank=True,
verbose_name="Year you discovered Billy Joel's music/became a fan")
profile_picture = models.ImageField(upload_to=get_upload_profile_pic_file_name,
blank=True, null=True)
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
Here is the official documentation on extending the user model.
This is how you would extend the default Django User model. You would want to use a ForeignKey, and then you can use dot notation to access the fields of the User model.
Here:
from django.contrib.auth.models import User
class MyMember(models.Model):
user = models.ForeignKey(User)
birthday = models.DateField()
def __unicode__(self):
# the default "username" field in the django user model
return self.user.username