2013-06-23 9 views
5

पर 'पहले से मौजूद' त्रुटि दे रहा है मुझे अब तक का सबसे अजीब त्रुटि मिल रही है। मेरे पास एक व्यक्ति मॉडलDjango अद्वितीय, शून्य और खाली CharField व्यवस्थापक पृष्ठ

class Person(models.Model): 
    user = models.OneToOneField(User, primary_key=True) 
    facebook_id = models.CharField(max_length=225, unique=True, null=True, blank=True) 
    twitter_id = models.CharField(max_length=225, unique=True, null=True, blank=True) 
    suggested_person = models.BooleanField(default=False) 

मैंने हाल ही में twitter_id फ़ील्ड जोड़ा है। जब मैं Django व्यवस्थापक पृष्ठ का उपयोग, और एक suggested_person में 'व्यक्ति' को बदलने की कोशिश, मैं निम्नलिखित त्रुटि मिलती है:

Person with this Twitter id already exists. 

मैं यह त्रुटि बेहद अजीब है क्योंकि Facebook_id क्षेत्र में ठीक उसी बनाया गया है होना करने के लिए लगता है ट्विटर_आईडी फ़ील्ड के रूप में।

इसका कारण क्या हो सकता है?

उत्तर

1

चूंकि आपके पास null=True, blank=True और unique=True है, django None पर विचार कर रहा है या एक अद्वितीय प्रविष्टि के रूप में खाली है। अद्वितीय बाधा को हटाएं और कोड में विशिष्टता भाग को संभालें।

+1

मैंने ट्विटर_आईडी फ़ील्ड को हटा दिया और फिर इसे दक्षिण का उपयोग करने में फिर से जोड़ा।यह मुझे कोई समस्या नहीं दिए बिना ठीक काम कर रहा है – noahandthewhale

+2

Django खाली स्ट्रिंग '' 'के रूप में रिक्त फ़ील्ड का इलाज कर रहा है, और' अद्वितीय = True' एकाधिक प्रविष्टियों को मान '' ''' 'के साथ अनुमति नहीं देता है। हालांकि यह 'twitter_id = none'' के साथ कई प्रविष्टियों की अनुमति देगा। – Alasdair

-2

आप खाली मूल्य स्वीकार कर रहे हैं और उन्हें अद्वितीय होने की उम्मीद करते हैं। इसका मतलब यह है वहाँ केवल एक खाली twitter_id

आप कर सकते हैं

  • या तो अद्वितीय contraint
  • को दूर हटाने के खाली = सच
  • (क्षेत्र के लिए एक डिफ़ॉल्ट मान दे लेकिन डिफ़ॉल्ट रूप से एक प्रवेश किया जा सकता है अद्वितीय होने की आवश्यकता है)
+0

डिफ़ॉल्ट मान काम नहीं करेगा। फिर एक ही मुद्दा। रिक्त स्थान को हटाने से अधिक समस्याएं पैदा होंगी – karthikr

+0

ओह हाँ, अद्वितीय बाधा। लेकिन डिफ़ॉल्ट मान किसी फ़ंक्शन या किसी चीज़ से आ सकता है। –

16

यह एक पुराना है लेकिन मेरे पास अभी भी एक समान समस्या थी और हालांकि मैं एक वैकल्पिक समाधान प्रदान करता हूं।

मैं ऐसी परिस्थिति में हूं जहां मुझे नल = ट्रू, रिक्त = सही और अद्वितीय = सही के साथ एक CharField करने में सक्षम होना चाहिए। अगर मैं व्यवस्थापक पैनल में एक खाली स्ट्रिंग जमा करता हूं तो यह सबमिट नहीं करेगा क्योंकि रिक्त स्ट्रिंग अद्वितीय नहीं है।

इसे ठीक करने के लिए, मैं मॉडलफॉर्म में 'क्लीन' फ़ंक्शन को ओवरराइड करता हूं, और वहां मैं जांचता हूं कि यह एक खाली स्ट्रिंग है या परिणाम को तुरंत लौटाएं।

class MyModelChangeForm(forms.ModelForm): 

    class Meta: 
     model = models.MyModel 
     fields = ['email', 'name', 'something_unique_or_null',] 

    def clean_something_unique_or_null(self): 
     if self.cleaned_data['something_unique_or_null'] == "": 
      return None 
     else: 
      return self.cleaned_data['something_unique_or_null'] 

यह मॉडल फ़ील्ड पर अद्वितीय विशेषता बलिदान के बिना मेरे लिए समस्या को हल करता है।

उम्मीद है कि इससे मदद मिलती है।

संपादित करें: आपको बदलने की जरूरत है जहां मैंने आपके क्षेत्र के नाम पर "something_unique_or_null" रखा है। उदाहरण के लिए "clean_twitter_id"।

8

कोई भी जवाब स्पष्ट रूप से समस्या की जड़ का वर्णन नहीं करता है।

आम तौर पर db में आप एक क्षेत्र null=True, unique=True कर सकते हैं और यह काम करेंगे ... क्योंकि NULL != NULL। तो प्रत्येक खाली मूल्य अभी भी अद्वितीय माना जाता है।

लेकिन दुर्भाग्य से CharField रों Django (क्योंकि जब आप एक फार्म सब कुछ तारों के रूप में Django में आता है प्रस्तुत एक खाली स्ट्रिंग "" की बचत होगी, और तुम हो सकता है के लिए सचमुच एक खाली स्ट्रिंग "" बचाना चाहती थी - Django पता नहीं है अगर यह None में परिवर्तित करना चाहिए)

इसका मूल रूप से मतलब है कि आपको Django में CharField(unique=True, null=True, blank=True) का उपयोग नहीं करना चाहिए। जैसा कि अन्य ने नोट किया है कि आपको शायद डीबी-स्तरीय अद्वितीय बाधा छोड़नी है और मॉडल में अपनी अनूठी जांच करनी है।

आगे के संदर्भ के लिए, यहां देखें: https://code.djangoproject.com/ticket/4136
(दुर्भाग्य से कोई अच्छा समाधान लेखन के समय का फैसला किया)

+2

पायथन में, 'कोई नहीं == कोई नहीं'। –

+0

ओह, आप सही हैं, अपडेट करेंगे – Anentropic

+3

टिकट 4136 अब तय किया गया है। Django 1.11+ में आप 'CharField (अद्वितीय = सही, शून्य = सही, खाली = सही)' का उपयोग कर रिक्त मान मैन्युअल रूप से 'none' में कनवर्ट किए बिना कर सकते हैं। – Alasdair

4

समस्या के मूल कि Django-खाली स्ट्रिंग के रूप में रिक्त मान जारी रहती है, और अशक्त रूप में नहीं है । इसे ठीक करने के लिए, आप के रूप में निम्नानुसार CharField उपवर्ग सकते:

class CharNullField(models.CharField): 
    description = "CharField that stores NULL" 

    def get_db_prep_value(self, value, connection=None, prepared=False): 
     value = super(CharNullField, self).get_db_prep_value(value, connection, prepared) 
     if value=="": 
      return None 
     else: 
      return value 

तो get_db_prep_value यह यकीन है कि अशक्त कायम हो जाता है

1

यह न प्रपत्र स्तर पर मॉडल स्तर पर इस को हल करने के लिए महत्वपूर्ण है कि कर देगा, डेटा के बाद से आयात स्क्रिप्ट के माध्यम से, शैल इत्यादि के माध्यम से एपीआई के माध्यम से प्रवेश कर सकते हैं। Charfield पर null=True सेट करने का नकारात्मक हिस्सा यह है कि कॉलम खाली तारों और एनयूएलएल दोनों के साथ समाप्त हो सकता है, जो थोड़ा अस्पष्ट है लेकिन आम तौर पर मेरे अनुभव में कोई समस्या नहीं है। यदि आप उस अस्पष्टता के साथ जीने के इच्छुक हैं, तो यहां कुछ चरणों में इसे कैसे करें:

1) फ़ील्ड पर null=True, blank=True सेट करें और परिवर्तन में माइग्रेट करें।

2) इतना है कि सभी मौजूदा रिक्त स्ट्रिंग NULLs में बदल दिया जाता अपने डेटा की मालिश:

def save(self, *args, **kwargs): 
    # Empty strings are not unique, but we can save multiple NULLs 
    if not self.somefield: 
     self.somefield = None 

    super().save(*args, **kwargs) # Python3-style super() 

4) पर unique=True सेट करें:

items = Foo.objects.all() 
for item in items: 
    if not item.somefield: 
    item.somefield = None 
    item.save() 

3) अपने मॉडल के लिए एक कस्टम save() विधि जोड़ें क्षेत्र और साथ ही माइग्रेट भी।

अब आप somefield को खाली या एक अद्वितीय मूल्य के रूप में स्टोर करने में सक्षम होंगे चाहे आप व्यवस्थापक या किसी अन्य डेटा प्रविष्टि विधि का उपयोग कर रहे हों।

आप कई माइग्रेशन देखना पसंद नहीं करते हैं, तो यहां एक भी प्रवास में ऐसा करने का एक उदाहरण है:

from __future__ import unicode_literals 
from django.db import migrations, models 

def set_nulls(apps, schema_editor): 
    Event = apps.get_model("events", "Event") 
    events = Event.objects.all() 
    for e in events: 
     if not e.wdid: 
      e.wdid = None 
      e.save() 


class Migration(migrations.Migration): 

    dependencies = [ 
     ('events', '0008_something'), 
    ] 

    operations = [ 
     migrations.AlterField(
      model_name='event', 
      name='wdid', 
      field=models.CharField(blank=True, max_length=32, null=True), 
     ), 
     migrations.RunPython(set_nulls), 
     migrations.AlterField(
      model_name='event', 
      name='wdid', 
      field=models.CharField(blank=True, max_length=32, null=True, unique=True), 
     ), 
    ] 
7

Django 1.11 में, प्रपत्र CharFields एक empty_value तर्क है, जो आप का उपयोग करने की अनुमति देता होगा None यदि फ़ील्ड खाली है।

मॉडल के CharField में null=True में Django व्यवस्थापक, will automatically set empty_value=None सहित मॉडल फॉर्म शामिल हैं।

इसलिए, आप अद्वितीय बाधा के कारण समस्याओं के बिना अपने मॉडल CharField में एक साथ null=True, और blank=Trueunique=True उपयोग करने के लिए सक्षम हो जाएगा।

संबंधित मुद्दे