I have an abstract model class userabstract which has fields id(primary key), name(char field) and email(email field).
I am inheriting this class in two classes user, usertemp. After signing up, i want the data to be stored in usertemp. When user clicks on confirmation mail then that data will be transferred to user class.
But whats happening is, whenever someone signs up, usertemp model is updated instead of creating a new one. Same thing is happening with user class
Here is the code for models and views
class UserAbstract(models.Model):
id = models.AutoField(db_column='ID', primary_key=True, default=1) # Field name made lowercase.
name = models.CharField(db_column='NAME', max_length=100, default='') # Field name made lowercase.
email = models.CharField(db_column='EMAIL', max_length=100, default='') # Field name made lowercase.
def __str__(self):
return self.name
class Meta:
abstract = True
#python_2_unicode_compatible
class User(UserAbstract):
def __str__(self):
return self.name ;
class Meta:
managed = True
db_table = 'User'
#python_2_unicode_compatible
class Validation(models.Model):
key = models.AutoField(primary_key=True)
key_data = models.CharField(max_length=100, default='')
create_time = models.DateTimeField()
expire_time = models.DateTimeField()
def __str__(self):
return self.key_data
#python_2_unicode_compatible
class UserTemp(UserAbstract):
validation_key = models.ForeignKey(Validation, models.DO_NOTHING, related_name='+', default='') # Field name made lowercase.
verified = models.BooleanField(default=False)
def __str__(self):
return self.validation_key.key_data
views.py
def signup(request):
if request.method == 'POST':
form = FormTemp(request.POST, request.FILES)
if form.is_valid():
primary = form.cleaned_data['email']
try:
qdict = {}
qdict['email'] = primary
user = UserTemp.objects.get(**qdict)
if user.verified==True:
return HttpResponse("Account already exists")
except:
pass
email = form.cleaned_data['email']
signer = hashlib.sha256()
signer.update(primary)
validation_key = signer.hexdigest()
confirm_key = request.build_absolute_uri('/signup-confirm/')+'?key='+validation_key
send_mail('Confirm Your Mail', confirm_key, settings.EMAIL_HOST_USER, [email,])
valid = Validation(key_data=validation_key, create_time=datetime.now(), expire_time=datetime.now()+timedelta(days=30))
valid.save()
argsdict = {}
argsdict['name'] = form.cleaned_data['name']
argsdict['email'] = form.cleaned_data['email']
argsdict['validation_key'] = valid
argsdict['verified'] = False
usertemp = UserTemp(**argsdict)
usertemp.save()
return HttpResponse("Confirmation mail sent")
else:
return HttpResponse('Invalid Data')
else:
return HttpResponse('What are you doing here ? Tresspass')
The valid.save() is working fine and every time validation key is being saved but the usertemp contains only one model and that is the most recent one.
When i tried force_insert=True then its telling me that duplicate entry exist with same primary key. As you can see, the primary key field id is AutoField then why django not creating a new model when i am writing usertemp = UserTemp(**argsdict)
The problem here is that you've given your AutoField a default value. You're telling Django to assign that field the value 1 if you don't provide it, which means that you keep writing rows with the same id.
So just get rid of that default.
The broader point to understand is that defaults are a Django-level feature, while AutoField is a database-level feature. From the perspective of the database, there's no difference between explicitly assigned column values and Django default column values.
Related
I'm creating a page that lets only admin add some assets. Each asset has a type. I have used a dropdown to select the asset_type. The selected value of asset_type gets passed into views.py but I can't get it written into the newly created asset object.
Here is my models.py
class assetType(models.Model):
title = models.CharField(max_length=150)
#property
def get_type(self):
return asset.objects.filter(asset_type=self.id)
def __str__(self):
return f"{self.title}"
class Meta:
verbose_name_plural = 'Asset Types'
class asset(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, null=False)
asset_type = models.ForeignKey('assetType', on_delete=models.CASCADE, null=True)
asset_name = models.CharField(max_length=30, null=True) #unique=True
location = models.CharField(max_length=30, null=True)
brand = models.CharField(max_length=30, null=True)
purchase_year = models.PositiveIntegerField(blank=True, null=True)
isActive = models.BooleanField(default=True, null=True)
currentOwner = models.ForeignKey(User, default='', null=True, on_delete=models.CASCADE)
Here is createAssetView from views.py
#user_passes_test(lambda u: u.is_superuser)
def createAssetView(request):
assetTypeList = assetType.objects.all() # use assetType.title
assettype = request.POST.get('asset-type')
assetname = request.POST.get('asset-name')
locationn = request.POST.get('location')
brandd = request.POST.get('brand')
purchaseyear = request.POST.get('purchase-year')
isActivve = request.POST.get('is-active','') == 'on'
cuser=request.user
context={
"cuser":request.user,
"asset_type_list":assetTypeList,
"asset_type":assettype,
"asset_name":assetname,
"location":locationn,
"brand":brandd,
"purchase_year":purchaseyear,
"isActive":isActivve,
'iterator':range(2014,2050)
}
if request.method == 'POST':
new_asset = asset()
new_asset.asset_type_title=request.POST.get('asset-type')
new_asset.asset_name=assetname
new_asset.location=locationn
new_asset.brand=brandd
new_asset.purchase_year=purchaseyear
new_asset.isActive=True if isActivve else False
new_asset.currentOwner=cuser
print(assettype) # PRINT assettype
new_asset.save()
return redirect('createAssets')
return render(request, 'assets/createAsset.html', context)
The PRINT assettype statement prints selected asset type from the form, so the value is getting passed to the view, how should I populate the table with it?
Any suggestions or help will be highly appreciated. Thanks!
new_asset.asset_type_title=request.POST.get('asset-type')
This is the line where your problem is. You can't assign a foreign object like that, it does not automatically search for a match in another model.
You need to either provide the object to be used as a foreign key, or the object's primary key.
So we find our database entry for the selected type:
target_type = assetType.objects.get(title=assettype)
# this assumes you use unique titles for each assetType, see below
and then provide the new asset either with the object itself:
new_asset.asset_type = target_type
or its primary key:
new_asset.asset_type_id = target_type.pk
I strongly reccomend spending more time with django's documentation to strengthen your understanding of how foreign object relation is implemented in django. At least review the tutorials that focus on that.
Also consider the following:
The title field of the assetType model is not limited to be unique. What happens if two assetTypes with the same title are created?
Repetition of request.POST.get('asset-type')
I want to find practice data based on the user primary key.
So when I open the url: localhost:8080/api/practice-filter?user=1 it will output all practice data based on the user with id 1.
model.py
class Practice(models.Model):
practice_id = models.BigAutoField(primary_key=True)
user = models.ForeignKey('User', models.DO_NOTHING, default=None)
score = models.SmallIntegerField(null=True)
class Meta:
managed = True
db_table = 'practice'
def __str__(self):
return str(self.practice_id)
class User(models.Model):
user_id = models.BigAutoField(primary_key=True)
fullname = models.CharField(max_length=50)
email = models.CharField(max_length=100)
password = models.TextField()
class Meta:
managed = True
db_table = 'user'
def __str__(self):
return self.fullname
view.py
#api_view(['GET'])
def practice_filter(request):
if request.method == 'GET':
exercises = Practice.objects.all()
user = request.GET.get('user', None)
if user is not None:
practice_filtered = exercises.filter(user__user__icontains=user)
exercises_serializer = PracticeSerializer(practice_filtered, many=True)
return JsonResponse(exercises_serializer.data, safe=False)
But when i run the above code i get an error :
Related Field got invalid lookup: user
How to solve this error?
I do not know what to do.
I'm still a beginner and need a lot of guidance.
Please help.
Thank you.
You can go through foreign key fields with __.
but there is no field called user in User Model.
If you want to filter by user's fullname you can do this:
practice_filtered = exercises.filter(user__fullname__icontains=user)
Good evening!
I have the following, a table containing my custom users (our dear Fellows) which will serve to login our users (by using the custom model).
◢ The custom backends with it's custom user model for the Fellows table.
from django.contrib.auth.hashers import check_password
from django.contrib.auth.models import User
from .models import CustomUser
class FellowBackend:
def authenticate(self, request, **kwargs):
'''Authenticates the user (custom model).'''
# Parameters
user_id = kwargs['username']
password = kwargs['password']
# Tentatives.
try:
user = CustomUser.objects.get(id = user_id)
# If the password matches.
if check_password(password, user.password):
return user
else:
# Triggers default login failed.
return None
except CustomUser.DoesNotExist:
return None
def get_user(self, user_id):
'''TODO: Test if this override is required.'''
try:
return CustomUser.objects.get(pk = user_id)
except CustomUser.DoesNotExist:
return None
◢ The custom user model.
class Faction(models.Model):
id = models.AutoField(db_column='ID', primary_key=True) # Field name made lowercase.
name = models.CharField(db_column='Name', max_length=64) # Field name made lowercase.
class Meta:
managed = False
db_table = 'Faction'
class CustomUser(AbstractBaseUser):
id = models.PositiveBigIntegerField(db_column='ID', primary_key=True) # ID.
display_name = models.CharField(db_column='Name', max_length=64, db_collation='utf8mb4_general_ci')
password = models.CharField(db_column='User_Password', max_length=256, blank=True, null=True)
gold = models.IntegerField(db_column='Gold') # Credits.
faction = models.ForeignKey('Faction', models.RESTRICT, db_column='Faction', default=1) # ID Faction.
last_login = models.DateTimeField(db_column='Last_Login', blank=True, null=True) # Last Login.
# Admin Panel Abstract Fields
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
USERNAME_FIELD = 'id'
REQUIRED_FIELD = [] # id (username) and password required by default.
class Meta:
managed = False
db_table = 'Fellows'
def __str__(self):
return self.display_name # Test.
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"""Is the user a member of staff?"""
return self.staff
#property
def is_active(self):
"""Is the user active?"""
return self.active
So far so good, I can connect, do my stuff and even access the admin panel to manage every registered models if I am part of the staff.
However, let us say I want to add permissions between members of the staff, someone I hire for example to manage exclusively the Items table (from app Armory) while the other admin can have a total access to the models from any app.
◢ The armory app will contain the Item model (and it's references).
class Rarity(models.Model):
...
class ItemType(models.Model):
...
class Item(models.Model):
id = models.AutoField(db_column='ID', primary_key=True) # Identifier
name = models.CharField(db_column='Name', unique=True, max_length=64) # Name of the item.
description = models.TextField(db_column='Description', max_length=512, blank=True, null=True) # Description of the item.
source = models.CharField(db_column='Source', max_length=128, blank=True, null=True) # Source icon of the item.
rarity = models.ForeignKey('Rarity', models.CASCADE, db_column='Rarity') # ID of the rarity.
item_type = models.ForeignKey('ItemType', models.CASCADE, db_column='Item_Type') # ID of the item type.
item_value = models.PositiveIntegerField(db_column='Item_Value') # Value of the item.
sell = models.BooleanField(db_column='Sell') # If the item can be sold.
gift = models.BooleanField(db_column='Gift') # If the item can be sent.
dismantle = models.BooleanField(db_column='Dismantle') # If the item can be dismantled.
world = models.BooleanField(db_column='World') # If the item can be found in the world (using the bot's !wheel command).
class Meta:
db_table = 'n_rpg_items'
def __str__(self):
return self.name
◢ And an articles app that will contain the Article model.
from django.conf import settings
from django.db import models
class Article(models.Model):
id = models.AutoField(db_column='ID', primary_key=True) # ID
author = models.ForeignKey(settings.AUTH_USER_MODEL, db_column="ID_User", on_delete=models.CASCADE) # User ID
title = models.CharField(db_column='Title', max_length=32) # Title
content = models.TextField(db_column='Content') # Content
posted = models.DateTimeField(db_column='Posted') # Date Posted
source = models.CharField(db_column='Source', max_length=64, blank=True, null=True) # Source picture url of the article.
class Meta:
managed = False
db_table = 'Articles'
def __str__(self):
return 'Article : ' + self.title
To be more precise, when logging in the admin panel, admin_a will only be able to manage Items, while admin_b will be able to manage everything, Items and Articles.
The problem is, I searched for a while, the doc didn't helped me and I can't find anything that satisfies what I want to achieve so I am probably doing this wrong...
I was thinking about doing my own admin backends by adding a Role in the Fellows table but soon there will be no more use of framework if I start reinventing the wheel... :(
If anybody could share with me which solutions are conceivable, even a start, I would greatly appreciate!
models.py
i have create foreignkey in table paymentsDetails i have stripe payment method which is working when user login session is created and by using session value i get the primarykey of that user by using 'ORM' method and then assign this primary key of specific user into the paymentdetails models field named as user_account_id
but i am getting error that i cannot assign 1 to PaymentsDetail.User_account_id must be a instance of UserAccountModel
class UserAccountModel(models.Model):
ContactEmail = models.EmailField(max_length=30)
FirstName = models.CharField(max_length=30)
LastName = models.CharField(max_length=40)
Counrty = models.CharField(max_length=50)
Phone = models.IntegerField()
ChooseUserName = models.CharField(max_length=30)
password = models.CharField(max_length=32)
EnterCaptcha = models.CharField(max_length=4)
payments = models.BooleanField(max_length=6, default=False)
showsponsor = models.CharField(max_length=30, default=False)
RegisteredDate = models.DateTimeField(auto_now_add=True, blank=True)
ActivationOn = models.DateField(auto_now_add=False,blank=True)
expiry_date = models.DateField(auto_now_add=False,blank=True)
def __str__(self):
return self.FirstName + ":" + self.ChooseUserName
class PaymentsDetail(models.Model):
refrer_name = models.CharField(max_length=32,default="", editable=False)
sponser_name = models.CharField(max_length=32)
status = models.CharField(default='comped', max_length=32)
s_id = models.CharField(max_length=32)
registered = models.DateTimeField(auto_now_add=True)
activated_date = models.DateField(auto_now_add=False)
Due_Date = models.DateField(auto_now_add=False)
payment = models.CharField(default='$',max_length=32)
User_Account_id = models.ForeignKey(UserAccountModel, on_delete=models.CASCADE, default=True, editable=True)
addprogrameReference = models.ForeignKey(AddProgramModel, on_delete=models.CASCADE, default=True, editable=True)
class Meta:
ordering = ['User_Account_id', 'addprogrameReference']
def str(self):
return self.refrer_name + ":" + self.user_account
i am getting the error
cannot assign 1 to PaymentsDetail.User_account_id must be a instance
of UserAccountModel
views.py
print("user payment"+str(charge.amount))
pays = str(charge.amount)
user_id = random.randint(0, 999) # returns a random integer
user = User.objects.get(username=str(rerredby))
userKey = user.pk
print("this one is for user upper")
# saving record
payment_insertion = PaymentsDetail.objects.create(
User_Account_id=userKey,
refrer_name=rerredby,
sponser_name=rerredby,
s_id=str(user_id),
registered=datetime.now(),
activated_date=datetime.now(),
Due_Date=datetime.now(),
payment=str(pays + "$"),
)
payment_insertion.save()
Simply change this string:
payment_insertion = PaymentsDetail.objects.create(
User_Account_id=user,
...)
You are trying to assign int object where Django expects an instance.
Your view implementation is not right. The model class expects the field User_Account_id to be an instance of of UserAccountModel (since, your model definition User_Account_id = models.ForeignKey(UserAccountModel, on_delete=models.CASCADE, default=True, editable=True) told it to expect it regardless of the your field name ending with an id). therefore, retrieve the UserAccountModel instance from db first.
However, if you still want to pass the id to instead of an object change the following in your view.
User_Account_id_id=userKey
ForeingKey fields can be populated by id instead of the concerned model object. But you have to append _id at the end of the field name e.g.
#models.py
class Author(models.Model):
name = models.CharField(max_length=250)
class Book(models.Model):
name = models.CharField(max_length=250)
author = models.ForeignKeyField(Author, on_delete=models.CASCADE)
# views.py
def create_book(request):
name = request.POST.get('name', '')
author_id = request.POST.get('author_id', '')
Book.objects.create(name=name, author_id=author_id)
return HttpResponse(status=201)
Notice that there is no author_id field defined in the Book model. This field is implicitly defined by django ORM once you defined author field as a ForeignKey reference to Author model.
I've been reading similar questions to mine but they didn't help me.
I'm getting this error while I try to submit my form:
Cannot assign "9": "Characterweapons.weaponid" must be a "Weapons" instance.
This "9" is the ID from the weapon I got from my form, so that's very good, but when I try to put it in my weaponid column in my table Characterweapons, it gives me the error.
models.py:
from __future__ import unicode_literals
from django.db import models
class Category(models.Model):
categoryid = models.AutoField(db_column='CategoryID', primary_key=True) # Field name made lowercase.
categoryname = models.CharField(db_column='CategoryName', max_length=50, blank=True, null=True) # Field name made lowercase.
class Meta:
managed = True
db_table = 'category'
def __str__(self):
return self.categoryname
class Characters(models.Model):
characterid = models.AutoField(db_column='CharacterID', primary_key=True) # Field name made lowercase.
name = models.CharField(db_column='Name', unique=True, max_length=255) # Field name made lowercase.
level = models.IntegerField(db_column='Level') # Field name made lowercase.
credits = models.IntegerField(db_column='Credits') # Field name made lowercase.
class Meta:
managed = True
db_table = 'characters'
def __str__(self):
return '%s %s %s' % (self.name, self.level, self.credits)
class Weapons(models.Model):
weaponid = models.AutoField(db_column='WeaponID', primary_key=True) # Field name made lowercase.
weaponname = models.CharField(db_column='WeaponName', unique=True, max_length=255) # Field name made lowercase.
class Meta:
managed = True
db_table = 'weapons'
def __str__(self):
return '%s %r' % (self.weaponname, self.weaponid)
class Characterweapons(models.Model):
characterid = models.ForeignKey(Characters, models.DO_NOTHING, db_column='CharacterID') # Field name made lowercase.
weaponid = models.ForeignKey(Weapons, models.DO_NOTHING, db_column='WeaponID', blank=True, null=True) # Field name made lowercase.
categoryid = models.ForeignKey(Category, models.DO_NOTHING, db_column='CategoryID', blank=True, null=True) # Field name made lowercase.
quantity = models.IntegerField(db_column='Quantity', blank=True, null=True) # Field name made lowercase.
class Meta:
managed = True
db_table = 'characterweapons'
def __str__(self):
return '%s' % (self.quantity)
class DjangoMigrations(models.Model):
app = models.CharField(max_length=255)
name = models.CharField(max_length=255)
applied = models.DateTimeField()
class Meta:
managed = True
db_table = 'django_migrations'
I don't know if it is a FK problem, PK... no idea and I cannot find information to solve it...
views.py: (where the error has to be):
def submission(request):
print("Registered successfully")
Name = request.POST["Name"]
Level = request.POST["Level"]
Credits = request.POST["Credits"]
Mainhand = request.POST["Mainhand"]
Offhand = request.POST["Offhand"]
info = Characters(name=Name,level=Level,credits=Credits)
info.save()
mh=
infomh = Weapons.objects.values_list('weaponid',flat=True)
a=0;
for a in infomh:
if a == Mainhand:
a = Mainhand;
print("a: ")
print(a)
print("Mainhand")
print(Mainhand)
print("infmh:")
print(infomh)
charid = Characters.objects.latest('characterid')
info_mh = Characterweapons(characterid=charid,categoryid=1,weaponid=a)
info_mh.save()
#info_oh = Characterweapons(characterid=charid,weaponid=9,categoryid=2)
#info_oh.save()
return return_charnames(request)
With these prints I made sure that the values of my weaponsID are correct, they are.
I also wanna point out that the value=9 in the column "weaponid" exists in "Weapons" table.
Thanks all.
I think you better first fix your models. In Django a ForeignKey is conceptually a reference to an object to which you refer, not the id. Of course in the database it is stored as an id, but that is a layer that you should not care much about.
So I would advice to first rename the fields like weaponid to weapon:
class Characterweapons(models.Model):
character = models.ForeignKey(Characters, models.DO_NOTHING, db_column='CharacterID')
weapon = models.ForeignKey(Weapons, models.DO_NOTHING, db_column='WeaponID', blank=True, null=True)
category = models.ForeignKey(Category, models.DO_NOTHING, db_column='CategoryID', blank=True, null=True)
quantity = models.IntegerField(db_column='Quantity', blank=True, null=True)
# ...
Now if you construct a ForeignKey with the name fieldname, Django actually introduces two fields: the fieldname which is - like said before - a reference to a model object to which the ForeignKey refers, and a field fieldname_id that stores the id (the primary key) of that object. These two fields thus act like "twins".
We can then rewrite the submission view like:
def submission(request):
print("Registered successfully")
name = request.POST["Name"]
level = request.POST["Level"]
credits = request.POST["Credits"]
mainhand = request.POST["Mainhand"]
offhand = request.POST["Offhand"]
info = Characters.objects.create(name=name, level=level,credits=credits)
if Weapons.objects.filter(weapon_id=mainhand).exists():
a = mainhand
info_mh = Characterweapons.objects.create(
character_id=info.pk,
category_id=1,
weapon_id=a
)
return return_charnames(request)
In the above I did some refactorings as well:
In Python variables in functions typically have lowercase names;
you do not need to loop over weapon_ids, you can use an EXISTS query, which is typically faster;
Instead of first constructing a model instance, and then obj.save() it, you can use Model.objects.create(..) instead;
you probably do not want to fetch the latest(..) value, but use the pk of the info object instead, since that is the one we constructed, and furthermore if there is no order defined (like here), the order can be any order the database likes, not per se the latest one added.
You probably still need to rewrite hardcoded identifiers (like a=1, and category_id=1, since it is perfectly possible that those objects do not exist in the database).
Your foreignkey weaponid in the model Characterweapons is a Weapon instance not only its id.
From that id, query the object and assign it.