জ্যাঙ্গো মডেলগুলির মধ্যে তালিকা সংরক্ষণের সবচেয়ে কার্যকর উপায় কোনটি?


146

বর্তমানে আমার কোডটিতে নীচের মতো সদৃশ প্রচুর পাইথন অবজেক্ট রয়েছে:

class MyClass():
  def __init__(self, name, friends):
      self.myName = name
      self.myFriends = [str(x) for x in friends]

এখন আমি এটিকে জ্যাঙ্গো মডেলে রূপান্তরিত করতে চাই, যেখানে self.myName একটি স্ট্রিং ক্ষেত্র, এবং self.myF Friendss হল স্ট্রিংগুলির একটি তালিকা।

from django.db import models

class myDjangoModelClass():
    myName = models.CharField(max_length=64)
    myFriends = ??? # what goes here?

যেহেতু তালিকাটি অজগরের একটি সাধারণ তথ্য কাঠামো, তাই আমি এটির জন্য একটি জ্যাঙ্গো মডেল ক্ষেত্র হওয়ার সম্ভাবনা নিয়েছিলাম। আমি জানি যে আমি একটি ম্যান্টি টোমনি বা ওয়ানটোমনি সম্পর্ক ব্যবহার করতে পারি তবে আমি কোডটিতে অতিরিক্ত অতিরিক্ত নির্দেশনা এড়াতে চাইছিলাম।

সম্পাদনা:

আমি এই সম্পর্কিত প্রশ্নটি যুক্ত করেছি , যা লোকেরা দরকারী মনে করতে পারে।


1
@ড্রোজি: আচ্ছা আমি সম্ভবত একটি আলাদা বাক্যাংশ ব্যবহার করতে পারতাম, তবে মূলত আমি যা বোঝাতে চেয়েছিলাম তা কি আমি স্ট্রিংয়ের একটি তালিকায় পাস করে স্ট্রিংগুলির একটি তালিকা ফিরে পেতে চাইতাম। আমি একগুচ্ছ ফ্রেন্ড অবজেক্ট তৈরি করতে চাই না এবং তাদের প্রত্যেকের জন্য inst.myF دوستs.add (ফ্রেন্ডঅবজ) কল করি। এটি যে এত কঠিন হবে তা নয়, তবে ...
শোক করুন

উত্তর:


77

এই সম্পর্কটি কি কোনও Friendsটেবিলের সাথে এক থেকে বহু বিদেশী কী সম্পর্ক হিসাবে ভাল প্রকাশ করা যায় না ? আমি বুঝতে পারি যে myFriendsএটি কেবল স্ট্রিং তবে আমি মনে করব যে আরও ভাল ডিজাইন হ'ল একটি Friendমডেল তৈরি MyClassকরা এবং ফলস্বরূপ টেবিলের সাথে একটি বিদেশী কী রিলেশনশিপ থাকবে।


15
আমি সম্ভবত এটিই শেষ করব, তবে আমি সত্যিই আশা করছিলাম এটির জন্য অন্তর্নিহিত কাঠামোটি তৈরি করা হত I আমি অনুমান করি যে আমি অলস।
শোক করুন

মার্জিত এবং সর্বাধিক সুন্দরভাবে ব্যাখ্যা করা।
টেসারাক্টার


129

"অকালীন অপটিমাইজেশন হ'ল সমস্ত অশুভের মূল"।

দৃ firm়ভাবে মনে রেখে, আসুন এটি করা যাক! আপনার অ্যাপ্লিকেশনগুলি একটি নির্দিষ্ট বিন্দুতে একবার আঘাত করলে, ডেনারমালাইজিং ডেটা খুব সাধারণ। সঠিকভাবে সম্পন্ন হয়েছে, এটি আরও কিছুটা গৃহকর্মের জন্য ব্যয় করে অনেক ব্যয়বহুল ডাটাবেস লুকআপ সংরক্ষণ করতে পারে।

কোনও listবন্ধুর নাম ফেরত দিতে আমাদের একটি কাস্টম জ্যাঙ্গো ফিল্ড শ্রেণি তৈরি করতে হবে যা অ্যাক্সেস পেলে একটি তালিকা ফিরে আসবে।

ডেভিড ক্র্যামার তার ব্লগে সেপ্রেটেডভ্যালুফিল্ড তৈরির জন্য একটি গাইড পোস্ট করেছিলেন। কোডটি এখানে:

from django.db import models

class SeparatedValuesField(models.TextField):
    __metaclass__ = models.SubfieldBase

    def __init__(self, *args, **kwargs):
        self.token = kwargs.pop('token', ',')
        super(SeparatedValuesField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        if not value: return
        if isinstance(value, list):
            return value
        return value.split(self.token)

    def get_db_prep_value(self, value):
        if not value: return
        assert(isinstance(value, list) or isinstance(value, tuple))
        return self.token.join([unicode(s) for s in value])

    def value_to_string(self, obj):
        value = self._get_val_from_obj(obj)
        return self.get_db_prep_value(value)

এই কোডটির যুক্তিটি পাইথন এবং তদ্বিপরীত থেকে ডেটাবেস থেকে মানগুলি ডিরিসালাইজেশন এবং ডিসরিয়ালাইজিংয়ের সাথে সম্পর্কিত। এখন আপনি সহজেই আমাদের কাস্টম ক্ষেত্রটি মডেল শ্রেণিতে আমদানি করতে এবং ব্যবহার করতে পারেন:

from django.db import models
from custom.fields import SeparatedValuesField 

class Person(models.Model):
    name = models.CharField(max_length=64)
    friends = SeparatedValuesField()

8
দুর্দান্ত উত্তরের জন্য +1, তবে আমরা ইতিমধ্যে এরকম কিছু করছি। এটি সত্যই সমস্ত মানকে এক স্ট্রিংয়ে স্কোয়াশ করছে তারপরে সেগুলি বিভক্ত করে। আমি অনুমান করি যে আমি একটি লিস্টোফস্ট্রিংফিল্ডের মতো আরও কিছু আশা করছিলাম যা প্রকৃতপক্ষে পৃথক টেবিল তৈরি করে এবং বিদেশী কীগুলি স্বয়ংক্রিয়ভাবে তৈরি করে। জ্যাঙ্গোতে এটি সম্ভব কিনা তা আমি নিশ্চিত নই। যদি এটি হয় এবং আমি একটি উত্তর খুঁজে পাই, তবে আমি এটি স্ট্যাকওভারফ্লোতে পোস্ট করব।
শোক করুন

2
যদি এটি হয় তবে আপনি ইনক্র্যাশ-এর ​​জাঙ্গো-ডেনর্ম খুঁজছেন। আপনি এটি গিথুব এ
jb।

3
+1 টি। তবে স্ট্রিংগুলিতে কমা নিয়ে সম্ভাব্য সমস্যা। জেসন থেকে সিরিয়ালাইজেশন এবং ডিসিরিয়ালাইজিং সম্পর্কে কী?
সবেলিয়াকভ

এটিকে বিদ্যমান মডেলটিতে যুক্ত করার চেষ্টা করছেন তবে my_vals = SeparatedValuesField(blank=True, default="")ন্যূনালগুলির কারণে ইন্টিগ্রিটিআরার পেয়ে যাচ্ছেন। ডিফল্ট যুক্তিটি কি সঠিকভাবে পার হচ্ছে না?
জন লেহম্যান ১৩

1
নোট করুন যে জ্যাঙ্গো ২.১ to_pythonএ আর পড়ার জন্য বলা হয় না। সুতরাং এই কাজটি করতে আপনাকে যুক্ত করতে হবে: def from_db_value(self, value, expression, connection, context): return self.to_python(value)
theadriangreen

46

জ্যাঙ্গোতে একটি তালিকা সংরক্ষণ করার একটি সহজ উপায় হ'ল এটি কেবল একটি জেএসএন স্ট্রিংয়ে রূপান্তর করা এবং তারপরে মডেলটিতে পাঠ্য হিসাবে সংরক্ষণ করা। তারপরে আপনি (জেএসএন) স্ট্রিংটিকে অজগর তালিকায় ফিরে রূপান্তর করে তালিকাটি পুনরুদ্ধার করতে পারেন। এখানে কীভাবে:

"তালিকা" আপনার জ্যাঙ্গো মডেলটিতে এভাবে সংরক্ষণ করা হবে:

class MyModel(models.Model):
    myList = models.TextField(null=True) # JSON-serialized (text) version of your list

আপনার দর্শন / নিয়ামক কোডে:

ডাটাবেসটিতে তালিকাটি সংরক্ষণ করা:

import simplejson as json # this would be just 'import json' in Python 2.7 and later
...
...

myModel = MyModel()
listIWantToStore = [1,2,3,4,5,'hello']
myModel.myList = json.dumps(listIWantToStore)
myModel.save()

ডাটাবেস থেকে তালিকাটি পুনরুদ্ধার করা হচ্ছে:

jsonDec = json.decoder.JSONDecoder()
myPythonList = jsonDec.decode(myModel.myList)

ধারণামূলকভাবে, এখানে যা চলছে তা এখানে:

>>> myList = [1,2,3,4,5,'hello']
>>> import simplejson as json
>>> myJsonList = json.dumps(myList)
>>> myJsonList
'[1, 2, 3, 4, 5, "hello"]'
>>> myJsonList.__class__
<type 'str'>
>>> jsonDec = json.decoder.JSONDecoder()
>>> myPythonList = jsonDec.decode(myJsonList)
>>> myPythonList
[1, 2, 3, 4, 5, u'hello']
>>> myPythonList.__class__
<type 'list'>

8
দুর্ভাগ্যক্রমে এটি আপনাকে
জাঙ্গো

25

যদি আপনি পোস্টগ্রিসের সাথে জ্যাঙ্গো> = 1.9 ব্যবহার করেন তবে আপনি অ্যারেফিল্ড সুবিধাগুলি ব্যবহার করতে পারেন

তথ্যের তালিকা সংরক্ষণের জন্য একটি ক্ষেত্র। বেশিরভাগ ফিল্ডের ধরণগুলি ব্যবহার করা যায়, আপনি কেবল বেস ফিল্ড হিসাবে অন্য ক্ষেত্রের উদাহরণটি পাস করেন। আপনি একটি আকার নির্দিষ্ট করতে পারেন। অ্যারেফিল্ডটি বহুমাত্রিক অ্যারেগুলি সঞ্চয় করতে বাসা বাঁধতে পারে।

অ্যারে ক্ষেত্রগুলিতে বাসা বাঁধাই সম্ভব:

from django.contrib.postgres.fields import ArrayField
from django.db import models

class ChessBoard(models.Model):
    board = ArrayField(
        ArrayField(
            models.CharField(max_length=10, blank=True),
            size=8,
        ),
        size=8,
    )

@ থানে-ব্রিফহল উল্লেখ করেছেন যেহেতু উপাদানগুলির সরাসরি জিজ্ঞাসা করাও সম্ভব। ডকুমেন্টেশন রেফারেন্স


2
এর বড় সুবিধা হ'ল আপনি অ্যারে ক্ষেত্র থেকে উপাদানগুলি সরাসরি জিজ্ঞাসা করতে পারেন।
থানা ব্রিমহল

@ থানব্রিমহল আপনি ঠিক বলেছেন হয়তো আমার এই তথ্য দিয়ে উত্তর আপডেট করা উচিত। ধন্যবাদ
ওলেন্দ্রনহ

দুঃখের বিষয়, মাইএসকিএল-এর কোনও সমাধান নেই
জোয়েল জি ম্যাথিউ

এটি কেবল পোস্টগ্রাসের সাথেই কাজ করে বলে উল্লেখ করা উচিত।
theadriangreen

1
জ্যাঙ্গো 1.8 এর অ্যারেফিল্ডও রয়েছে: ডকস.ডজ্যাঙ্গোপ্রজেক্ট /en/1.8/ref/contrib/postgres/fields
কনটেক্সটিফাই

15

যেহেতু এটি একটি পুরানো প্রশ্ন, এবং জ্যাঙ্গো কৌশলগুলি অবশ্যই এর থেকে উল্লেখযোগ্যভাবে পরিবর্তিত হয়েছে, এই উত্তরটি জাঙ্গো সংস্করণ 1.4 প্রতিবিম্বিত করে এবং সম্ভবত 1.5 এর জন্য প্রযোজ্য।

জ্যাঙ্গো ডিফল্টরূপে রিলেশনাল ডাটাবেস ব্যবহার করে; আপনার 'ইম ব্যবহার করা উচিত। ম্যানিওটোম্যানিফিল্ডের ব্যবহারের সাথে ডেটাবেস সম্পর্কের (বিদেশী কী বাধার) বন্ধুত্বের মানচিত্র। এটি করার ফলে আপনি ফ্রেন্ডলিস্টগুলির জন্য সম্পর্কিত ম্যানেজারগুলি ব্যবহার করতে পারবেন যা স্মার্ট ক্যোয়ারসেট ব্যবহার করে use আপনি যেমন সমস্ত উপলব্ধ পদ্ধতি ব্যবহার করতে পারেন filterবা values_list

ManyToManyFieldসম্পর্ক এবং বৈশিষ্ট্য ব্যবহার করে:

class MyDjangoClass(models.Model):
    name = models.CharField(...)
    friends = models.ManyToManyField("self")

    @property
    def friendlist(self):
        # Watch for large querysets: it loads everything in memory
        return list(self.friends.all())

আপনি এইভাবে কোনও ব্যবহারকারীর বন্ধু তালিকায় প্রবেশ করতে পারেন:

joseph = MyDjangoClass.objects.get(name="Joseph")
friends_of_joseph = joseph.friendlist

তবে খেয়াল করুন যে এই সম্পর্কগুলি প্রতিসম হয়: যদি জোসেফ ববের বন্ধু হয় তবে বব জোসেফের বন্ধু।


9
class Course(models.Model):
   name = models.CharField(max_length=256)
   students = models.ManyToManyField(Student)

class Student(models.Model):
   first_name = models.CharField(max_length=256)
   student_number = models.CharField(max_length=128)
   # other fields, etc...

   friends = models.ManyToManyField('self')

8

মনে রাখবেন অবশেষে এটি একটি সম্পর্কিত ডেটাবেসেই শেষ করতে হবে। সম্পর্ক ব্যবহার সত্যিই তাই হয় এই সমস্যা সমাধানের জন্য সাধারণ উপায়। আপনি যদি অবজেক্টে নিজেই একটি তালিকা সঞ্চয় করার জন্য জোর দিয়ে থাকেন তবে আপনি এটি উদাহরণস্বরূপ কমা-বিচ্ছিন্ন করে স্ট্রিংয়ে সংরক্ষণ করতে পারেন এবং তারপরে স্ট্রিংটিকে তালিকায় বিভক্ত এমন অ্যাকসেসর ফাংশন সরবরাহ করতে পারেন। এটির সাথে সাথে আপনি সর্বাধিক সংখ্যক স্ট্রিংয়ের মধ্যে সীমাবদ্ধ থাকবেন এবং আপনি দক্ষ অনুসন্ধানগুলি হারাবেন।


3
আমি ডেটাবেসটিকে এটি একটি সম্পর্ক হিসাবে সংরক্ষণ করার সাথে ভাল আছি, আমি আশা করছিলাম জ্যাঙ্গো মডেলগুলি ইতিমধ্যে আমার পক্ষে সেই অংশটি বিমূর্ত করে তুলেছে। অ্যাপের পক্ষ থেকে আমি সর্বদা এটির স্ট্রিংগুলির তালিকা হিসাবে বিবেচনা করতে চাই।
শোক করুন

7

আপনি যদি পোস্টগ্রিজ ব্যবহার করছেন তবে আপনি এরকম কিছু ব্যবহার করতে পারেন:

class ChessBoard(models.Model):

    board = ArrayField(
        ArrayField(
            models.CharField(max_length=10, blank=True),
            size=8,
        ),
        size=8,
    )

আপনার যদি আরও বিশদ প্রয়োজন হয় তবে নীচের লিঙ্কে পড়তে পারেন: https://docs.djangoproject.com/pt-br/1.9/ref/contrib/postgres/fields/


4

জ্যাঙ্গো পিকল ফিল্ড ব্যবহার করে আপনি কার্যত যে কোনও বস্তু সঞ্চয় করতে পারেন, এই এই স্নিপেট:

http://www.djangosnippets.org/snippets/513/


3
না, তা নয়। স্নিপেটের বিবরণ পড়ুন।
হ্যারল্ড

নতুন পিপিআইপিথন.আর.পিপি / ডিজেঙ্গো-পিকলেফিল্ড একই কাজটি করে (এছাড়াও ডিবি স্বতন্ত্র)
ম্যাসাগ্রান

3

জ্যাঙ্গো মডেলটিতে স্ট্রিংগুলির একটি তালিকা সংরক্ষণ করা:

class Bar(models.Model):
    foo = models.TextField(blank=True)

    def set_list(self, element):
        if self.foo:
            self.foo = self.foo + "," + element
        else:
            self.foo = element

    def get_list(self):
        if self.foo:
            return self.foo.split(",")
        else:
            None

এবং আপনি এটিকে কল করতে পারেন:

bars = Bar()
bars.set_list("str1")
bars.set_list("str2")
list = bars.get_list()
if list is not None:
    for bar in list:
        print bar
else:
    print "List is empty."      

2

আমার সমাধান, এটি কারও সহায়ক হতে পারে:

import json
from django.db import models


class ExampleModel(models.Model):
    _list = models.TextField(default='[]')

    @property
    def list(self):
        return json.loads(self._list)

    @list.setter
    def list(self, value):
        self._list = json.dumps(self.list + value)

1

এক থেকে একাধিক সম্পর্ক (বন্ধু থেকে অভিভাবক শ্রেণীর কাছে এফকে) ব্যবহার করা আপনার অ্যাপ্লিকেশনটিকে আরও স্কেলযোগ্য করে তুলবে (যেহেতু আপনি তুচ্ছভাবে সাধারণ নামটির বাইরে অতিরিক্ত বৈশিষ্ট্য সহ বন্ধুত্বের বিষয়টিকে প্রসারিত করতে পারেন)। এবং এইভাবে এটি সেরা উপায়


3
এটি স্কেলিবিলিটি নয়, এটি এক্সটেনসিবিলিটি। প্রায়শই একজন অন্যজনের দামে হয়। এই ক্ষেত্রে, যদি আপনি জানেন যে আপনার কাছে সর্বদা স্ট্রিংগুলির একটি তালিকা প্রয়োজন, আপনি একটি ব্যয়বহুল যোগদান এড়াতে পারেন, এইভাবে আপনার কোডটিকে আরও স্কেলযোগ্য করে তুলবে (অর্থাত্ স্বীকৃতি থেকে আরও পারফরম্যান্ট)।
ডাস্টিন রাসেনার

উপরের কয়েকটা সতর্কতার সাথে: 1) আপনি জানেন যে আপনি কখনই সেই ডেটার বিরুদ্ধে কোয়েরি করতে চান না এবং 2) স্টোরেজ প্রক্রিয়াজাতকরণ শক্তি এবং মেমরির তুলনায় এখনও কম সস্তা (কে জানে, কোয়ান্টাম কম্পিউটিংয়ের সাথে এটি পরিবর্তন হতে পারে)
ডাস্টিন রাসেনার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.