Home > OS >  Django models - how to assign as ForeignKey
Django models - how to assign as ForeignKey

Time:05-15

My lab has a models.py as below:

class Book(models.Model):
    isbn = models.CharField(max_length=10, unique=True)
    name = models.CharField(max_length=100)
    published_year = models.IntegerField()
    total_qty = models.IntegerField()
    current_qty = models.IntegerField()
    max_duration = models.IntegerField()
    author = models.ForeignKey(Author, on_delete=models.PROTECT)
    category = models.ForeignKey(Category, on_delete=models.PROTECT)
    def __str__(self):
        return self.name

class BookCopy(models.Model):
    class Status:
        AVAILABLE = 1
        BORROW =2 
        LOST = 3
    barcode = models.CharField(max_length=30, unique=True)
    buy_date = models.DateField(null=True, blank=True)
    status = models.IntegerField()
    book = models.ForeignKey(Book, on_delete=models.PROTECT)
    def __str__(self):
        return self.barcode
class User(models.Model):
    username = models.CharField(max_length=30, unique=True)
    fullname = models.CharField(max_length=100, null=True)
    phone = models.CharField(max_length=10, null=True)
    def __str__(self):
        return self.fullname

class BookBorrow(models.Model):
    class Status:
        BORROWING = 1
        RETURNED = 2
    borrow_date = models.DateField()
    deadline = models.DateField()
    return_date = models.DateField(null=True)
    status = models.IntegerField()
    book_copy = models.ForeignKey(BookCopy, on_delete=models.PROTECT)
    book_name = models.ForeignKey(Book, on_delete=models.PROTECT)
    user = models.ForeignKey(User, on_delete=models.PROTECT)

And i wrote the api for borrow_book function like below:

@csrf_exempt 
def muon_sach(request):
    body = request.POST 
    username = body.get('username')
    barcode = body.get('barcode')
    user = User.objects.filter(username=username).first()
    bookcopy = BookCopy.objects.filter(barcode = barcode).first()
    if not user:
        return HttpResponse(json.dumps({
            'error':"Nguoi dung khong ton tai"
        }))
    if not bookcopy:
        return HttpResponse(json.dumps({
            'error':"ma sach khong ton tai"
        }))       
    book_borrow = BookBorrow()
    # resp = []
    book_borrow.user = user
    book_borrow.book_copy = bookcopy
    book_borrow.borrow_date = datetime.now()
    book_borrow.deadline = datetime.now()   timedelta(days=bookcopy.book.max_duration)
    book_borrow.status = BookBorrow.Status.BORROWING
    book_borrow.book_name = bookcopy.book.name
    book_borrow.save()

    bookcopy.status = BookCopy.Status.BORROW
    bookcopy.save()
    bookcopy.book.current_qty -=1
    bookcopy.book.save()

    return HttpResponse(json.dumps({'success':True}))

however when i test with postman (give username and barcode), it gets the error xxx "BookBorrow.book_name" must be a "Book" instance."

Could you please advise where incorrect and assist me correct it ? Appreciate for any assist

CodePudding user response:

You have specified book_name to be a Foreign Key to Book, and you try to assign to it the book.name value.

Either you need to set this field as a CharField or you need to rename the field from book_name to book and use book_borrow.book = bookcopy.book

CodePudding user response:

You have to do the following:

@csrf_exempt 
def muon_sach(request):
    # ... more code here
    bookcopy = BookCopy.objects.filter(barcode = barcode).first()
    book_borrow.book_name = bookcopy.book
    book_borrow.save()
    # ... more code here
    return HttpResponse(json.dumps({'success':True}))

So in the definition of your model you can see that book_name has the following structure:

class BookBorrow(models.Model):
    # ... More code here
    book_name = models.ForeignKey(Book, on_delete=models.PROTECT)
    user = models.ForeignKey(User, on_delete=models.PROTECT)

It is clear that BookBorrow.book_name must accept a Book instance. So when you pass in you code book_borrow.book_copy = bookcopy it is passing a BookCopy instance so that's the error.

borrow_copy.book is the appropiate.

  • Related